testchar.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. /**
  2. * Test the UTF-8 decoding routines
  3. *
  4. * author: Daniel Veillard
  5. * copy: see Copyright for the status of this software.
  6. */
  7. #define XML_DEPRECATED
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <libxml/tree.h>
  11. #include <libxml/parser.h>
  12. #include <libxml/parserInternals.h>
  13. int lastError;
  14. static void errorHandler(void *unused, const xmlError *err) {
  15. if ((unused == NULL) && (err != NULL) && (lastError == 0)) {
  16. lastError = err->code;
  17. }
  18. }
  19. char document1[100] = "<doc>XXXX</doc>";
  20. char document2[100] = "<doc foo='XXXX'/>";
  21. static int testDocumentRangeByte1(xmlParserCtxtPtr ctxt, char *document,
  22. int len, char *data, int forbid1, int forbid2) {
  23. int i;
  24. xmlDocPtr res;
  25. for (i = 0;i <= 0xFF;i++) {
  26. lastError = 0;
  27. xmlCtxtReset(ctxt);
  28. data[0] = (char) i;
  29. res = xmlReadMemory(document, len, "test", NULL, 0);
  30. if ((i == forbid1) || (i == forbid2)) {
  31. if ((lastError == 0) || (res != NULL)) {
  32. fprintf(stderr,
  33. "Failed to detect invalid char for Byte 0x%02X: %c\n",
  34. i, i);
  35. return(1);
  36. }
  37. }
  38. else if ((i == '<') || (i == '&')) {
  39. if ((lastError == 0) || (res != NULL)) {
  40. fprintf(stderr,
  41. "Failed to detect illegal char %c for Byte 0x%02X\n", i, i);
  42. return(1);
  43. }
  44. }
  45. else if (((i < 0x20) || (i >= 0x80)) &&
  46. (i != 0x9) && (i != 0xA) && (i != 0xD)) {
  47. if ((lastError != XML_ERR_INVALID_CHAR) && (res != NULL)) {
  48. fprintf(stderr,
  49. "Failed to detect invalid char for Byte 0x%02X\n", i);
  50. return(1);
  51. }
  52. }
  53. else if (res == NULL) {
  54. fprintf(stderr,
  55. "Failed to parse valid char for Byte 0x%02X : %c\n", i, i);
  56. return(1);
  57. }
  58. if (res != NULL)
  59. xmlFreeDoc(res);
  60. }
  61. return(0);
  62. }
  63. static int testDocumentRangeByte2(xmlParserCtxtPtr ctxt, char *document,
  64. int len, char *data) {
  65. int i, j;
  66. xmlDocPtr res;
  67. for (i = 0x80;i <= 0xFF;i++) {
  68. for (j = 0;j <= 0xFF;j++) {
  69. lastError = 0;
  70. xmlCtxtReset(ctxt);
  71. data[0] = (char) i;
  72. data[1] = (char) j;
  73. res = xmlReadMemory(document, len, "test", NULL, 0);
  74. /* if first bit of first char is set, then second bit must too */
  75. if ((i & 0x80) && ((i & 0x40) == 0)) {
  76. if ((lastError == 0) || (res != NULL)) {
  77. fprintf(stderr,
  78. "Failed to detect invalid char for Bytes 0x%02X 0x%02X\n",
  79. i, j);
  80. return(1);
  81. }
  82. }
  83. /*
  84. * if first bit of first char is set, then second char first
  85. * bits must be 10
  86. */
  87. else if ((i & 0x80) && ((j & 0xC0) != 0x80)) {
  88. if ((lastError == 0) || (res != NULL)) {
  89. fprintf(stderr,
  90. "Failed to detect invalid char for Bytes 0x%02X 0x%02X\n",
  91. i, j);
  92. return(1);
  93. }
  94. }
  95. /*
  96. * if using a 2 byte encoding then the value must be greater
  97. * than 0x80, i.e. one of bits 5 to 1 of i must be set
  98. */
  99. else if ((i & 0x80) && ((i & 0x1E) == 0)) {
  100. if ((lastError == 0) || (res != NULL)) {
  101. fprintf(stderr,
  102. "Failed to detect invalid char for Bytes 0x%02X 0x%02X\n",
  103. i, j);
  104. return(1);
  105. }
  106. }
  107. /*
  108. * if third bit of first char is set, then the sequence would need
  109. * at least 3 bytes, but we give only 2 !
  110. */
  111. else if ((i & 0xE0) == 0xE0) {
  112. if ((lastError == 0) || (res != NULL)) {
  113. fprintf(stderr,
  114. "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x00\n",
  115. i, j);
  116. return(1);
  117. }
  118. }
  119. /*
  120. * We should see no error in remaining cases
  121. */
  122. else if ((lastError != 0) || (res == NULL)) {
  123. fprintf(stderr,
  124. "Failed to parse document for Bytes 0x%02X 0x%02X\n", i, j);
  125. return(1);
  126. }
  127. if (res != NULL)
  128. xmlFreeDoc(res);
  129. }
  130. }
  131. return(0);
  132. }
  133. /**
  134. * testDocumentRanges:
  135. *
  136. * Test the correct UTF8 character parsing in context of XML documents
  137. * Those are in-context injection tests checking the parser behaviour on
  138. * edge case values at different point in content, beginning and end of
  139. * CDATA in text or in attribute values.
  140. */
  141. static int testDocumentRanges(void) {
  142. xmlParserCtxtPtr ctxt;
  143. char *data;
  144. int test_ret = 0;
  145. /*
  146. * Set up a parsing context using the first document as
  147. * the current input source.
  148. */
  149. ctxt = xmlNewParserCtxt();
  150. if (ctxt == NULL) {
  151. fprintf(stderr, "Failed to allocate parser context\n");
  152. return(1);
  153. }
  154. printf("testing 1 byte char in document: 1");
  155. fflush(stdout);
  156. data = &document1[5];
  157. data[0] = ' ';
  158. data[1] = ' ';
  159. data[2] = ' ';
  160. data[3] = ' ';
  161. /* test 1 byte injection at beginning of area */
  162. test_ret += testDocumentRangeByte1(ctxt, &document1[0], strlen(document1),
  163. data, -1, -1);
  164. printf(" 2");
  165. fflush(stdout);
  166. data[0] = ' ';
  167. data[1] = ' ';
  168. data[2] = ' ';
  169. data[3] = ' ';
  170. /* test 1 byte injection at end of area */
  171. test_ret += testDocumentRangeByte1(ctxt, &document1[0], strlen(document1),
  172. data + 3, -1, -1);
  173. printf(" 3");
  174. fflush(stdout);
  175. data = &document2[10];
  176. data[0] = ' ';
  177. data[1] = ' ';
  178. data[2] = ' ';
  179. data[3] = ' ';
  180. /* test 1 byte injection at beginning of area */
  181. test_ret += testDocumentRangeByte1(ctxt, &document2[0], strlen(document2),
  182. data, '\'', -1);
  183. printf(" 4");
  184. fflush(stdout);
  185. data[0] = ' ';
  186. data[1] = ' ';
  187. data[2] = ' ';
  188. data[3] = ' ';
  189. /* test 1 byte injection at end of area */
  190. test_ret += testDocumentRangeByte1(ctxt, &document2[0], strlen(document2),
  191. data + 3, '\'', -1);
  192. printf(" done\n");
  193. printf("testing 2 byte char in document: 1");
  194. fflush(stdout);
  195. data = &document1[5];
  196. data[0] = ' ';
  197. data[1] = ' ';
  198. data[2] = ' ';
  199. data[3] = ' ';
  200. /* test 2 byte injection at beginning of area */
  201. test_ret += testDocumentRangeByte2(ctxt, &document1[0], strlen(document1),
  202. data);
  203. printf(" 2");
  204. fflush(stdout);
  205. data[0] = ' ';
  206. data[1] = ' ';
  207. data[2] = ' ';
  208. data[3] = ' ';
  209. /* test 2 byte injection at end of area */
  210. test_ret += testDocumentRangeByte2(ctxt, &document1[0], strlen(document1),
  211. data + 2);
  212. printf(" 3");
  213. fflush(stdout);
  214. data = &document2[10];
  215. data[0] = ' ';
  216. data[1] = ' ';
  217. data[2] = ' ';
  218. data[3] = ' ';
  219. /* test 2 byte injection at beginning of area */
  220. test_ret += testDocumentRangeByte2(ctxt, &document2[0], strlen(document2),
  221. data);
  222. printf(" 4");
  223. fflush(stdout);
  224. data[0] = ' ';
  225. data[1] = ' ';
  226. data[2] = ' ';
  227. data[3] = ' ';
  228. /* test 2 byte injection at end of area */
  229. test_ret += testDocumentRangeByte2(ctxt, &document2[0], strlen(document2),
  230. data + 2);
  231. printf(" done\n");
  232. xmlFreeParserCtxt(ctxt);
  233. return(test_ret);
  234. }
  235. static int
  236. testCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
  237. const xmlChar *oldcur;
  238. int c, err, len2;
  239. lastError = 0;
  240. c = xmlCurrentChar(ctxt, len);
  241. ctxt->input->flags = 0;
  242. err = lastError;
  243. oldcur = ctxt->input->cur;
  244. lastError = 0;
  245. xmlNextChar(ctxt);
  246. ctxt->input->flags = 0;
  247. len2 = ctxt->input->cur - oldcur;
  248. ctxt->input->cur = oldcur;
  249. if ((*ctxt->input->cur != 0) && (err != lastError)) {
  250. fprintf(stderr, "xmlCurrentChar and xmlNextChar report different "
  251. "errors: %d %d\n", err, lastError);
  252. return(-1);
  253. }
  254. if ((err == 0) && (*len != len2)) {
  255. fprintf(stderr, "xmlCurrentChar and xmlNextChar report different "
  256. "lengths: %d %d\n", *len, len2);
  257. return(-1);
  258. }
  259. lastError = err;
  260. return(c);
  261. }
  262. static int testCharRangeByte1(xmlParserCtxtPtr ctxt) {
  263. int i = 0;
  264. int len, c;
  265. char *data = (char *) ctxt->input->cur;
  266. data[1] = 0;
  267. data[2] = 0;
  268. data[3] = 0;
  269. for (i = 0;i <= 0xFF;i++) {
  270. data[0] = (char) i;
  271. ctxt->nbErrors = 0;
  272. c = testCurrentChar(ctxt, &len);
  273. if (c < 0)
  274. continue;
  275. if ((i == 0) || (i >= 0x80)) {
  276. /* we must see an error there */
  277. if (lastError != XML_ERR_INVALID_CHAR) {
  278. fprintf(stderr,
  279. "Failed to detect invalid char for Byte 0x%02X\n", i);
  280. return(1);
  281. }
  282. } else if (i == 0xD) {
  283. if ((c != 0xA) || (len != 1)) {
  284. fprintf(stderr, "Failed to convert char for Byte 0x%02X\n", i);
  285. return(1);
  286. }
  287. } else if ((c != i) || (len != 1)) {
  288. fprintf(stderr, "Failed to parse char for Byte 0x%02X\n", i);
  289. return(1);
  290. }
  291. }
  292. return(0);
  293. }
  294. static int testCharRangeByte2(xmlParserCtxtPtr ctxt) {
  295. int i, j;
  296. int len, c;
  297. char *data = (char *) ctxt->input->cur;
  298. data[2] = 0;
  299. data[3] = 0;
  300. for (i = 0x80;i <= 0xFF;i++) {
  301. for (j = 0;j <= 0xFF;j++) {
  302. data[0] = (char) i;
  303. data[1] = (char) j;
  304. ctxt->nbErrors = 0;
  305. c = testCurrentChar(ctxt, &len);
  306. if (c < 0)
  307. continue;
  308. /* if first bit of first char is set, then second bit must too */
  309. if ((i & 0x80) && ((i & 0x40) == 0)) {
  310. if (lastError != XML_ERR_INVALID_CHAR) {
  311. fprintf(stderr,
  312. "Failed to detect invalid char for Bytes 0x%02X 0x%02X\n",
  313. i, j);
  314. return(1);
  315. }
  316. }
  317. /*
  318. * if first bit of first char is set, then second char first
  319. * bits must be 10
  320. */
  321. else if ((i & 0x80) && ((j & 0xC0) != 0x80)) {
  322. if (lastError != XML_ERR_INVALID_CHAR) {
  323. fprintf(stderr,
  324. "Failed to detect invalid char for Bytes 0x%02X 0x%02X: %d\n",
  325. i, j, c);
  326. return(1);
  327. }
  328. }
  329. /*
  330. * if using a 2 byte encoding then the value must be greater
  331. * than 0x80, i.e. one of bits 5 to 1 of i must be set
  332. */
  333. else if ((i & 0x80) && ((i & 0x1E) == 0)) {
  334. if (lastError != XML_ERR_INVALID_CHAR) {
  335. fprintf(stderr,
  336. "Failed to detect invalid char for Bytes 0x%02X 0x%02X: %d\n",
  337. i, j, c);
  338. return(1);
  339. }
  340. }
  341. /*
  342. * if third bit of first char is set, then the sequence would need
  343. * at least 3 bytes, but we give only 2 !
  344. */
  345. else if ((i & 0xE0) == 0xE0) {
  346. if (lastError != XML_ERR_INVALID_CHAR) {
  347. fprintf(stderr,
  348. "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x00\n",
  349. i, j);
  350. return(1);
  351. }
  352. }
  353. /*
  354. * We should see no error in remaining cases
  355. */
  356. else if ((lastError != 0) || (len != 2)) {
  357. fprintf(stderr,
  358. "Failed to parse char for Bytes 0x%02X 0x%02X\n", i, j);
  359. return(1);
  360. }
  361. /*
  362. * Finally check the value is right
  363. */
  364. else if (c != (j & 0x3F) + ((i & 0x1F) << 6)) {
  365. fprintf(stderr,
  366. "Failed to parse char for Bytes 0x%02X 0x%02X: expect %d got %d\n",
  367. i, j, ((j & 0x3F) + ((i & 0x1F) << 6)), c);
  368. return(1);
  369. }
  370. }
  371. }
  372. return(0);
  373. }
  374. static int testCharRangeByte3(xmlParserCtxtPtr ctxt) {
  375. int i, j, k, K;
  376. int len, c;
  377. unsigned char lows[6] = {0, 0x80, 0x81, 0xC1, 0xFF, 0xBF};
  378. char *data = (char *) ctxt->input->cur;
  379. int value;
  380. data[3] = 0;
  381. for (i = 0xE0;i <= 0xFF;i++) {
  382. for (j = 0;j <= 0xFF;j++) {
  383. for (k = 0;k < 6;k++) {
  384. data[0] = (char) i;
  385. data[1] = (char) j;
  386. K = lows[k];
  387. data[2] = (char) K;
  388. value = (K & 0x3F) + ((j & 0x3F) << 6) + ((i & 0xF) << 12);
  389. ctxt->nbErrors = 0;
  390. c = testCurrentChar(ctxt, &len);
  391. if (c < 0)
  392. continue;
  393. /*
  394. * if fourth bit of first char is set, then the sequence would need
  395. * at least 4 bytes, but we give only 3 !
  396. */
  397. if ((i & 0xF0) == 0xF0) {
  398. if (lastError != XML_ERR_INVALID_CHAR) {
  399. fprintf(stderr,
  400. "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n",
  401. i, j, K, data[3]);
  402. return(1);
  403. }
  404. }
  405. /*
  406. * The second and the third bytes must start with 10
  407. */
  408. else if (((j & 0xC0) != 0x80) || ((K & 0xC0) != 0x80)) {
  409. if (lastError != XML_ERR_INVALID_CHAR) {
  410. fprintf(stderr,
  411. "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X\n",
  412. i, j, K);
  413. return(1);
  414. }
  415. }
  416. /*
  417. * if using a 3 byte encoding then the value must be greater
  418. * than 0x800, i.e. one of bits 4 to 0 of i must be set or
  419. * the 6th byte of data[1] must be set
  420. */
  421. else if (((i & 0xF) == 0) && ((j & 0x20) == 0)) {
  422. if (lastError != XML_ERR_INVALID_CHAR) {
  423. fprintf(stderr,
  424. "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X\n",
  425. i, j, K);
  426. return(1);
  427. }
  428. }
  429. /*
  430. * There are values that are not allowed in UTF-8
  431. */
  432. else if ((value > 0xD7FF) && (value <0xE000)) {
  433. if (lastError != XML_ERR_INVALID_CHAR) {
  434. fprintf(stderr,
  435. "Failed to detect invalid char 0x%04X for Bytes 0x%02X 0x%02X 0x%02X\n",
  436. value, i, j, K);
  437. return(1);
  438. }
  439. }
  440. /*
  441. * We should see no error in remaining cases
  442. */
  443. else if ((lastError != 0) || (len != 3)) {
  444. fprintf(stderr,
  445. "Failed to parse char for Bytes 0x%02X 0x%02X 0x%02X\n",
  446. i, j, K);
  447. return(1);
  448. }
  449. /*
  450. * Finally check the value is right
  451. */
  452. else if (c != value) {
  453. fprintf(stderr,
  454. "Failed to parse char for Bytes 0x%02X 0x%02X 0x%02X: expect %d got %d\n",
  455. i, j, data[2], value, c);
  456. return(1);
  457. }
  458. }
  459. }
  460. }
  461. return(0);
  462. }
  463. static int testCharRangeByte4(xmlParserCtxtPtr ctxt) {
  464. int i, j, k, K, l, L;
  465. int len, c;
  466. unsigned char lows[6] = {0, 0x80, 0x81, 0xC1, 0xFF, 0xBF};
  467. char *data = (char *) ctxt->input->cur;
  468. int value;
  469. data[4] = 0;
  470. for (i = 0xF0;i <= 0xFF;i++) {
  471. for (j = 0;j <= 0xFF;j++) {
  472. for (k = 0;k < 6;k++) {
  473. for (l = 0;l < 6;l++) {
  474. data[0] = (char) i;
  475. data[1] = (char) j;
  476. K = lows[k];
  477. data[2] = (char) K;
  478. L = lows[l];
  479. data[3] = (char) L;
  480. value = (L & 0x3F) + ((K & 0x3F) << 6) + ((j & 0x3F) << 12) +
  481. ((i & 0x7) << 18);
  482. ctxt->nbErrors = 0;
  483. c = testCurrentChar(ctxt, &len);
  484. if (c < 0)
  485. continue;
  486. /*
  487. * if fifth bit of first char is set, then the sequence would need
  488. * at least 5 bytes, but we give only 4 !
  489. */
  490. if ((i & 0xF8) == 0xF8) {
  491. if (lastError != XML_ERR_INVALID_CHAR) {
  492. fprintf(stderr,
  493. "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n",
  494. i, j, K, data[3]);
  495. return(1);
  496. }
  497. }
  498. /*
  499. * The second, third and fourth bytes must start with 10
  500. */
  501. else if (((j & 0xC0) != 0x80) || ((K & 0xC0) != 0x80) ||
  502. ((L & 0xC0) != 0x80)) {
  503. if (lastError != XML_ERR_INVALID_CHAR) {
  504. fprintf(stderr,
  505. "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n",
  506. i, j, K, L);
  507. return(1);
  508. }
  509. }
  510. /*
  511. * if using a 3 byte encoding then the value must be greater
  512. * than 0x10000, i.e. one of bits 3 to 0 of i must be set or
  513. * the 6 or 5th byte of j must be set
  514. */
  515. else if (((i & 0x7) == 0) && ((j & 0x30) == 0)) {
  516. if (lastError != XML_ERR_INVALID_CHAR) {
  517. fprintf(stderr,
  518. "Failed to detect invalid char for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n",
  519. i, j, K, L);
  520. return(1);
  521. }
  522. }
  523. /*
  524. * There are values in that are not allowed in UTF-8
  525. */
  526. else if (((value > 0xD7FF) && (value < 0xE000)) ||
  527. (value > 0x10FFFF)) {
  528. if (lastError != XML_ERR_INVALID_CHAR) {
  529. fprintf(stderr,
  530. "Failed to detect invalid char 0x%04X for Bytes 0x%02X 0x%02X 0x%02X 0x%02X\n",
  531. value, i, j, K, L);
  532. return(1);
  533. }
  534. }
  535. /*
  536. * We should see no error in remaining cases
  537. */
  538. else if ((lastError != 0) || (len != 4)) {
  539. fprintf(stderr,
  540. "Failed to parse char for Bytes 0x%02X 0x%02X 0x%02X\n",
  541. i, j, K);
  542. return(1);
  543. }
  544. /*
  545. * Finally check the value is right
  546. */
  547. else if (c != value) {
  548. fprintf(stderr,
  549. "Failed to parse char for Bytes 0x%02X 0x%02X 0x%02X: expect %d got %d\n",
  550. i, j, data[2], value, c);
  551. return(1);
  552. }
  553. }
  554. }
  555. }
  556. }
  557. return(0);
  558. }
  559. /**
  560. * testCharRanges:
  561. *
  562. * Test the correct UTF8 character parsing in isolation i.e.
  563. * not when parsing a full document, this is less expensive and we can
  564. * cover the full range of UTF-8 chars accepted by XML-1.0
  565. */
  566. static int testCharRanges(void) {
  567. char data[5];
  568. xmlParserCtxtPtr ctxt;
  569. xmlParserInputBufferPtr buf;
  570. xmlParserInputPtr input;
  571. int test_ret = 0;
  572. memset(data, 0, 5);
  573. /*
  574. * Set up a parsing context using the above data buffer as
  575. * the current input source.
  576. */
  577. ctxt = xmlNewParserCtxt();
  578. if (ctxt == NULL) {
  579. fprintf(stderr, "Failed to allocate parser context\n");
  580. return(1);
  581. }
  582. buf = xmlParserInputBufferCreateStatic(data, sizeof(data),
  583. XML_CHAR_ENCODING_NONE);
  584. if (buf == NULL) {
  585. fprintf(stderr, "Failed to allocate input buffer\n");
  586. test_ret = 1;
  587. goto error;
  588. }
  589. input = xmlNewInputStream(ctxt);
  590. if (input == NULL) {
  591. xmlFreeParserInputBuffer(buf);
  592. test_ret = 1;
  593. goto error;
  594. }
  595. input->filename = NULL;
  596. input->buf = buf;
  597. input->cur =
  598. input->base = xmlBufContent(input->buf->buffer);
  599. input->end = input->base + 4;
  600. inputPush(ctxt, input);
  601. printf("testing char range: 1");
  602. fflush(stdout);
  603. test_ret += testCharRangeByte1(ctxt);
  604. printf(" 2");
  605. fflush(stdout);
  606. test_ret += testCharRangeByte2(ctxt);
  607. printf(" 3");
  608. fflush(stdout);
  609. test_ret += testCharRangeByte3(ctxt);
  610. printf(" 4");
  611. fflush(stdout);
  612. test_ret += testCharRangeByte4(ctxt);
  613. printf(" done\n");
  614. fflush(stdout);
  615. error:
  616. xmlFreeParserCtxt(ctxt);
  617. return(test_ret);
  618. }
  619. static int
  620. testUserEncoding(void) {
  621. /*
  622. * Create a document encoded as UTF-16LE with an ISO-8859-1 encoding
  623. * declaration, then parse it with xmlReadMemory and the encoding
  624. * argument set to UTF-16LE.
  625. */
  626. xmlDocPtr doc = NULL;
  627. const char *start = "<?xml version='1.0' encoding='ISO-8859-1'?><d>";
  628. const char *end = "</d>";
  629. char *buf = NULL;
  630. xmlChar *text;
  631. int startSize = strlen(start);
  632. int textSize = 100000; /* Make sure to exceed internal buffer sizes. */
  633. int endSize = strlen(end);
  634. int totalSize = startSize + textSize + endSize;
  635. int k = 0;
  636. int i;
  637. int ret = 1;
  638. buf = xmlMalloc(2 * totalSize);
  639. for (i = 0; start[i] != 0; i++) {
  640. buf[k++] = start[i];
  641. buf[k++] = 0;
  642. }
  643. for (i = 0; i < textSize; i++) {
  644. buf[k++] = 'x';
  645. buf[k++] = 0;
  646. }
  647. for (i = 0; end[i] != 0; i++) {
  648. buf[k++] = end[i];
  649. buf[k++] = 0;
  650. }
  651. doc = xmlReadMemory(buf, 2 * totalSize, NULL, "UTF-16LE", 0);
  652. if (doc == NULL) {
  653. fprintf(stderr, "failed to parse document\n");
  654. goto error;
  655. }
  656. text = doc->children->children->content;
  657. for (i = 0; i < textSize; i++) {
  658. if (text[i] != 'x') {
  659. fprintf(stderr, "text node has wrong content at offset %d\n", k);
  660. goto error;
  661. }
  662. }
  663. ret = 0;
  664. error:
  665. xmlFreeDoc(doc);
  666. xmlFree(buf);
  667. return ret;
  668. }
  669. #if defined(LIBXML_PUSH_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
  670. static char *
  671. convert(xmlCharEncodingHandlerPtr handler, const char *utf8, int size,
  672. int *outSize) {
  673. char *ret;
  674. int inlen;
  675. int res;
  676. inlen = size;
  677. *outSize = size * 2;
  678. ret = xmlMalloc(*outSize);
  679. if (ret == NULL)
  680. return(NULL);
  681. res = handler->output(BAD_CAST ret, outSize, BAD_CAST utf8, &inlen);
  682. if ((res < 0) || (inlen != size)) {
  683. xmlFree(ret);
  684. return(NULL);
  685. }
  686. return(ret);
  687. }
  688. static int
  689. testUserEncodingPush(void) {
  690. xmlCharEncodingHandlerPtr handler;
  691. xmlParserCtxtPtr ctxt;
  692. xmlDocPtr doc;
  693. char buf[] =
  694. "\xEF\xBB\xBF"
  695. "<?xml version='1.0' encoding='ISO-8859-1'?>\n"
  696. "<d>text</d>\n";
  697. char *utf16;
  698. int utf16Size;
  699. int ret = 1;
  700. handler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF16LE);
  701. utf16 = convert(handler, buf, sizeof(buf) - 1, &utf16Size);
  702. ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
  703. xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_UTF16LE);
  704. xmlParseChunk(ctxt, utf16, utf16Size, 0);
  705. xmlParseChunk(ctxt, NULL, 0, 1);
  706. doc = ctxt->myDoc;
  707. if ((doc != NULL) &&
  708. (doc->children != NULL) &&
  709. (doc->children->children != NULL) &&
  710. (xmlStrcmp(doc->children->children->content, BAD_CAST "text") == 0))
  711. ret = 0;
  712. xmlFreeDoc(doc);
  713. xmlFreeParserCtxt(ctxt);
  714. xmlFree(utf16);
  715. return(ret);
  716. }
  717. static int
  718. testUTF8Chunks(void) {
  719. xmlParserCtxtPtr ctxt;
  720. xmlChar *out;
  721. int outSize;
  722. char *buf;
  723. int i;
  724. int ret = 0;
  725. ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
  726. xmlParseChunk(ctxt, "<d>", 3, 0);
  727. xmlParseChunk(ctxt, "\xF0", 1, 0);
  728. xmlParseChunk(ctxt, "\x9F", 1, 0);
  729. xmlParseChunk(ctxt, "\x98", 1, 0);
  730. xmlParseChunk(ctxt, "\x8A", 1, 0);
  731. xmlParseChunk(ctxt, "</d>", 4, 1);
  732. xmlDocDumpMemory(ctxt->myDoc, &out, &outSize);
  733. if (strcmp((char *) out,
  734. "<?xml version=\"1.0\"?>\n<d>&#x1F60A;</d>\n") != 0) {
  735. fprintf(stderr, "failed UTF-8 chunk test 1\n");
  736. ret += 1;
  737. }
  738. xmlFree(out);
  739. xmlFreeDoc(ctxt->myDoc);
  740. xmlFreeParserCtxt(ctxt);
  741. ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
  742. xmlParseChunk(ctxt, "<d>", 3, 0);
  743. /*
  744. * Create a chunk longer than XML_PARSER_BIG_BUFFER_SIZE (300) ending
  745. * with an incomplete UTF-8 sequence.
  746. */
  747. buf = xmlMalloc(1000 * 2 + 1);
  748. for (i = 0; i < 2000; i += 2)
  749. memcpy(buf + i, "\xCE\xB1", 2);
  750. buf[i] = '\xCE';
  751. xmlParseChunk(ctxt, buf, 2001, 0);
  752. xmlFree(buf);
  753. xmlParseChunk(ctxt, "\xB1</d>", 4, 0);
  754. xmlParseChunk(ctxt, NULL, 0, 0);
  755. xmlDocDumpMemory(ctxt->myDoc, &out, &outSize);
  756. if (strncmp((char *) out, "<?xml version=\"1.0\"?>\n<d>", 25) != 0) {
  757. fprintf(stderr, "failed UTF-8 chunk test 2-1\n");
  758. ret += 1;
  759. goto error;
  760. }
  761. for (i = 25; i < 25 + 1001 * 7; i += 7) {
  762. if (memcmp(out + i, "&#x3B1;", 7) != 0) {
  763. fprintf(stderr, "failed UTF-8 chunk test 2-2 %d\n", i);
  764. ret += 1;
  765. goto error;
  766. }
  767. }
  768. if (strcmp((char *) out + i, "</d>\n") != 0) {
  769. fprintf(stderr, "failed UTF-8 chunk test 2-3\n");
  770. ret += 1;
  771. goto error;
  772. }
  773. error:
  774. xmlFree(out);
  775. xmlFreeDoc(ctxt->myDoc);
  776. xmlFreeParserCtxt(ctxt);
  777. return(ret);
  778. return(0);
  779. }
  780. #endif
  781. int main(void) {
  782. int ret = 0;
  783. /*
  784. * this initialize the library and check potential ABI mismatches
  785. * between the version it was compiled for and the actual shared
  786. * library used.
  787. */
  788. LIBXML_TEST_VERSION
  789. /*
  790. * Catch errors separately
  791. */
  792. xmlSetStructuredErrorFunc(NULL, errorHandler);
  793. /*
  794. * Run the tests
  795. */
  796. ret += testCharRanges();
  797. ret += testDocumentRanges();
  798. ret += testUserEncoding();
  799. #if defined(LIBXML_PUSH_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
  800. ret += testUserEncodingPush();
  801. ret += testUTF8Chunks();
  802. #endif
  803. /*
  804. * Cleanup function for the XML library.
  805. */
  806. xmlCleanupParser();
  807. return(ret ? 1 : 0);
  808. }