diff options
| -rw-r--r-- | src/xplist.c | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/src/xplist.c b/src/xplist.c index 91b4645..e4eb56a 100644 --- a/src/xplist.c +++ b/src/xplist.c | |||
| @@ -518,7 +518,7 @@ static char* get_text_content(parse_ctx ctx, const char* tag, int skip_ws, int u | |||
| 518 | if (i >= len) { | 518 | if (i >= len) { |
| 519 | break; | 519 | break; |
| 520 | } | 520 | } |
| 521 | if (str+i > entp+1) { | 521 | if (str+i >= entp+1) { |
| 522 | int entlen = str+i - entp; | 522 | int entlen = str+i - entp; |
| 523 | if (!strncmp(entp, "amp", 3)) { | 523 | if (!strncmp(entp, "amp", 3)) { |
| 524 | /* the '&' is already there */ | 524 | /* the '&' is already there */ |
| @@ -530,9 +530,57 @@ static char* get_text_content(parse_ctx ctx, const char* tag, int skip_ws, int u | |||
| 530 | *(entp-1) = '<'; | 530 | *(entp-1) = '<'; |
| 531 | } else if (!strncmp(entp, "gt", 2)) { | 531 | } else if (!strncmp(entp, "gt", 2)) { |
| 532 | *(entp-1) = '>'; | 532 | *(entp-1) = '>'; |
| 533 | } else if (*entp == '#') { | ||
| 534 | /* numerical character reference */ | ||
| 535 | uint64_t val = 0; | ||
| 536 | char* ep = NULL; | ||
| 537 | if (entlen > 8) { | ||
| 538 | PLIST_XML_ERR("Invalid numerical character reference encountered, sequence too long: &%.*s;\n", entlen, entp); | ||
| 539 | return NULL; | ||
| 540 | } | ||
| 541 | if (*(entp+1) == 'x' || *(entp+1) == 'X') { | ||
| 542 | if (entlen < 3) { | ||
| 543 | PLIST_XML_ERR("Invalid numerical character reference encountered, sequence too short: &%.*s;\n", entlen, entp); | ||
| 544 | return NULL; | ||
| 545 | } | ||
| 546 | val = strtoull(entp+2, &ep, 16); | ||
| 547 | } else { | ||
| 548 | if (entlen < 2) { | ||
| 549 | PLIST_XML_ERR("Invalid numerical character reference encountered, sequence too short: &%.*s;\n", entlen, entp); | ||
| 550 | return NULL; | ||
| 551 | } | ||
| 552 | val = strtoull(entp+1, &ep, 10); | ||
| 553 | } | ||
| 554 | if (val == 0 || val > 0x10FFFF || ep-entp != entlen) { | ||
| 555 | PLIST_XML_ERR("Invalid numerical character reference found: &%.*s;\n", entlen, entp); | ||
| 556 | return NULL; | ||
| 557 | } | ||
| 558 | /* convert to UTF8 */ | ||
| 559 | if (val >= 0x10000) { | ||
| 560 | /* four bytes */ | ||
| 561 | *(entp-1) = (char)(0xF0 + ((val >> 18) & 0x7)); | ||
| 562 | *(entp+0) = (char)(0x80 + ((val >> 12) & 0x3F)); | ||
| 563 | *(entp+1) = (char)(0x80 + ((val >> 6) & 0x3F)); | ||
| 564 | *(entp+2) = (char)(0x80 + (val & 0x3F)); | ||
| 565 | entp+=3; | ||
| 566 | } else if (val >= 0x800) { | ||
| 567 | /* three bytes */ | ||
| 568 | *(entp-1) = (char)(0xE0 + ((val >> 12) & 0xF)); | ||
| 569 | *(entp+0) = (char)(0x80 + ((val >> 6) & 0x3F)); | ||
| 570 | *(entp+1) = (char)(0x80 + (val & 0x3F)); | ||
| 571 | entp+=2; | ||
| 572 | } else if (val >= 0x80) { | ||
| 573 | /* two bytes */ | ||
| 574 | *(entp-1) = (char)(0xC0 + ((val >> 6) & 0x1F)); | ||
| 575 | *(entp+0) = (char)(0x80 + (val & 0x3F)); | ||
| 576 | entp++; | ||
| 577 | } else { | ||
| 578 | /* one byte */ | ||
| 579 | *(entp-1) = (char)(val & 0x7F); | ||
| 580 | } | ||
| 533 | } else { | 581 | } else { |
| 534 | /* unexpected entity, replace with ? */ | 582 | PLIST_XML_ERR("Invalid entity encountered: &%.*s;\n", entlen, entp); |
| 535 | *(entp-1) = '?'; | 583 | return NULL; |
| 536 | } | 584 | } |
| 537 | memmove(entp, str+i+1, len - i); | 585 | memmove(entp, str+i+1, len - i); |
| 538 | i -= entlen; | 586 | i -= entlen; |
