1 /* 2 * Copyright (c) 2006, 2023 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 */ 9 10 #include <sm/gen.h> 11 SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.10 2013-11-22 20:51:43 ca Exp $") 12 13 #include <stdio.h> 14 #include <sm/sendmail.h> 15 #include <sm/assert.h> 16 #include <sm/heap.h> 17 #include <sm/string.h> 18 #include <sm/test.h> 19 20 extern bool SmTestVerbose; 21 22 void 23 show_diff(s1, s2) 24 const char *s1; 25 const char *s2; 26 { 27 int i; 28 29 for (i = 0; s1[i] != '\0' && s2[i] != '\0'; i++) 30 { 31 if (s1[i] != s2[i]) 32 { 33 fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n", 34 i, (unsigned char) s1[i], 35 (unsigned char) s2[i]); 36 return; 37 } 38 } 39 if (s1[i] != s2[i]) 40 { 41 fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n", 42 i, (unsigned char) s1[i], (unsigned char) s2[i]); 43 } 44 } 45 46 char *quote_unquote __P((char *, char *, int, int, int)); 47 48 char * 49 quote_unquote(in, out, outlen, exp, mode) 50 char *in; 51 char *out; 52 int outlen; 53 int exp; 54 int mode; 55 { 56 char *obp, *bp; 57 char line_back[1024]; 58 char line_in[1024]; 59 int cmp; 60 61 sm_strlcpy(line_in, in, sizeof(line_in)); 62 obp = quote_internal_chars(in, out, &outlen, NULL); 63 bp = str2prt(line_in); 64 if (0 == mode) 65 dequote_internal_chars(obp, line_back, sizeof(line_back)); 66 else if (1 == mode) 67 dequote_internal_chars(obp, line_back, strlen(obp)); 68 else if (2 == mode) 69 dequote_internal_chars(obp, line_back, strlen(obp) + 1); 70 cmp = strcmp(line_in, line_back); 71 SM_TEST(exp == cmp); 72 if (cmp != exp && !SmTestVerbose) 73 { 74 fprintf(stderr, "in: %s\n", bp); 75 bp = str2prt(line_back); 76 fprintf(stderr, "out:%s\n", bp); 77 fprintf(stderr, "cmp=%d\n", cmp); 78 show_diff(in, line_back); 79 } 80 if (SmTestVerbose) 81 { 82 fprintf(stderr, "%s -> ", bp); 83 bp = str2prt(obp); 84 fprintf(stderr, "%s\n", bp); 85 fprintf(stderr, "cmp=%d\n", cmp); 86 } 87 return obp; 88 } 89 90 struct sm_qic_S 91 { 92 char *qic_in; 93 char *qic_out; 94 int qic_exp; 95 }; 96 97 typedef struct sm_qic_S sm_qic_T; 98 99 100 int 101 main(argc, argv) 102 int argc; 103 char *argv[]; 104 { 105 char line_in[1024], line[256], line_out[32], *obp; 106 int i, los, cmp, mode; 107 sm_qic_T inout[] = { 108 { "", "", 0 } 109 , { "\t", "\t", 0 } 110 , { "\tuser", "\tuser", 0 } 111 , { "abcdef", "abcdef", 0 } 112 , { "01234567890123456789", "01234567890123456789", 0 } 113 , { "\\", "\\", 0 } 114 , { "\\A", "\\A", 0 } 115 , { "01234567890123456789\001", "01234567890123456789\001", 116 0 } 117 , { "012345\2067890123456789", "012345\377\2067890123456789", 118 0 } 119 , { "\377", "\377\377", 0 } 120 , { "\240", "\240", 0 } 121 , { "\220", "\377\220", 0 } 122 , { "\240\220", "\240\377\220", 0 } 123 , { "\377\377", "\377\377\377\377", 0 } 124 , { "\377a\377b", "\377\377a\377\377b", 0 } 125 , { "\376a\377b", "\376a\377\377b", 0 } 126 , { "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240", 127 "\377\200\377\201\377\202\377\203\377\204\377\205\377\206\377\207\377\210\377\211\377\212\377\213\377\214\377\215\377\216\377\217\377\220\377\221\377\222\377\223\377\224\377\225\377\226\377\227\377\230\377\231\377\232\377\233\377\234\377\235\377\236\377\237\240", 128 0 } 129 , { NULL, NULL, 0 } 130 }; 131 132 sm_test_begin(argc, argv, "test meta quoting"); 133 mode = 0; 134 if (argc > 1) 135 mode = atoi(argv[1]); 136 for (i = 0; i < sizeof(line_out); i++) 137 line_out[i] = '\0'; 138 for (i = 0; i < sizeof(line_in); i++) 139 line_in[i] = '\0'; 140 for (i = 0; i < sizeof(line_in) / 2; i++) 141 { 142 char ch; 143 144 ch = 0200 + i; 145 if ('\0' == ch) 146 ch = '0'; 147 line_in[i] = ch; 148 } 149 los = sizeof(line_out) / 2; 150 obp = quote_unquote(line_in, line_out, los, 0, mode); 151 if (obp != line_out) 152 SM_FREE(obp); 153 154 for (i = 0; i < sizeof(line_in); i++) 155 line_in[i] = '\0'; 156 for (i = 0; i < sizeof(line_in) / 2; i++) 157 { 158 char ch; 159 160 ch = 0200 + i; 161 if ('\0' == ch) 162 ch = '0'; 163 line_in[i] = ch; 164 } 165 los = sizeof(line_in); 166 obp = quote_unquote(line_in, line_in, los, 0, mode); 167 if (obp != line_in) 168 SM_FREE(obp); 169 170 for (i = 0; inout[i].qic_in != NULL; i++) 171 { 172 los = sizeof(line_out) / 2; 173 obp = quote_unquote(inout[i].qic_in, line_out, los, 174 inout[i].qic_exp, mode); 175 cmp = strcmp(inout[i].qic_out, obp); 176 SM_TEST(inout[i].qic_exp == cmp); 177 if (inout[i].qic_exp != cmp && !SmTestVerbose) 178 { 179 char *bp; 180 181 bp = str2prt(obp); 182 fprintf(stderr, "got: %s\n", bp); 183 bp = str2prt(inout[i].qic_out); 184 fprintf(stderr, "exp:%s\n", bp); 185 fprintf(stderr, "cmp=%d\n", cmp); 186 show_diff(inout[i].qic_in, inout[i].qic_out); 187 } 188 if (obp != line_out) 189 SM_FREE(obp); 190 } 191 192 /* use same buffer for in and out */ 193 for (i = 0; inout[i].qic_in != NULL; i++) 194 { 195 bool same; 196 197 same = strcmp(inout[i].qic_in, inout[i].qic_out) == 0; 198 los = sm_strlcpy(line, inout[i].qic_in, sizeof(line)); 199 SM_TEST(los + 1 < sizeof(line)); 200 ++los; 201 obp = quote_unquote(line, line, los, inout[i].qic_exp, mode); 202 cmp = strcmp(inout[i].qic_out, obp); 203 SM_TEST(inout[i].qic_exp == cmp); 204 if (inout[i].qic_exp != cmp && !SmTestVerbose) 205 { 206 char *bp; 207 208 bp = str2prt(obp); 209 fprintf(stderr, "got: %s\n", bp); 210 bp = str2prt(inout[i].qic_out); 211 fprintf(stderr, "exp:%s\n", bp); 212 fprintf(stderr, "cmp=%d\n", cmp); 213 show_diff(inout[i].qic_in, inout[i].qic_out); 214 } 215 if (obp != line) 216 { 217 SM_TEST(!same); 218 if (same) 219 show_diff(obp, inout[i].qic_out); 220 SM_FREE(obp); 221 } 222 } 223 224 /* use NULL buffer for out */ 225 for (i = 0; inout[i].qic_in != NULL; i++) 226 { 227 los = 0; 228 obp = quote_unquote(inout[i].qic_in, NULL, los, 229 inout[i].qic_exp, mode); 230 SM_TEST(obp != NULL); 231 cmp = strcmp(inout[i].qic_out, obp); 232 SM_TEST(inout[i].qic_exp == cmp); 233 if (inout[i].qic_exp != cmp && !SmTestVerbose) 234 { 235 char *bp; 236 237 bp = str2prt(obp); 238 fprintf(stderr, "got: %s\n", bp); 239 bp = str2prt(inout[i].qic_out); 240 fprintf(stderr, "exp:%s\n", bp); 241 fprintf(stderr, "cmp=%d\n", cmp); 242 show_diff(inout[i].qic_in, inout[i].qic_out); 243 } 244 } 245 246 los = -1; 247 obp = quote_internal_chars(NULL, NULL, &los, NULL); 248 SM_TEST(NULL == obp); 249 SM_TEST(-1 == los); 250 251 sm_strlcpy(line_in, "nothing", sizeof(line_in)); 252 los = -123; 253 obp = quote_internal_chars(line_in, NULL, &los, NULL); 254 SM_TEST(NULL != obp); 255 SM_TEST(los > 0); 256 257 return sm_test_end(); 258 } 259