diff options
Diffstat (limited to 'src/sax.c')
-rw-r--r-- | src/sax.c | 35 |
1 files changed, 31 insertions, 4 deletions
@@ -1,5 +1,5 @@ /* iksemel (XML parser for Jabber) -** Copyright (C) 2000-2004 Gurer Ozen <madcat@e-kolay.net> +** Copyright (C) 2000-2004 Gurer Ozen ** This code is free software; you can redistribute it and/or ** modify it under the terms of GNU Lesser General Public License. */ @@ -70,6 +70,7 @@ struct iksparser_struct { int uni_max; int uni_len; + unsigned int uni_char; }; iksparser * @@ -208,8 +209,24 @@ sax_core (iksparser *prs, char *buf, int len) if (0 == c || 0xFE == c || 0xFF == c) return IKS_BADXML; if (prs->uni_max) { if ((c & 0xC0) != 0x80) return IKS_BADXML; + prs->uni_char <<= 6; + prs->uni_char += (c & 0x3f); prs->uni_len++; - if (prs->uni_len == prs->uni_max) prs->uni_max = 0; + if (prs->uni_len == prs->uni_max) { + /* Security check: avoid overlong sequences */ + if (prs->uni_max == 2 && prs->uni_char < 0x80) + return IKS_BADXML; + if (prs->uni_max == 3 && prs->uni_char < 0x7FF) + return IKS_BADXML; + if (prs->uni_max == 4 && prs->uni_char < 0xffff) + return IKS_BADXML; + if (prs->uni_max == 5 && prs->uni_char < 0x1fffff) + return IKS_BADXML; + if (prs->uni_max == 6 && prs->uni_char < 0x3ffffff) + return IKS_BADXML; + prs->uni_max = 0; + prs->uni_char = 0; + } goto cont; } else { if (c & 0x80) { @@ -232,7 +249,7 @@ sax_core (iksparser *prs, char *buf, int len) } else { return IKS_BADXML; } - if ((c & mask) == 0) return IKS_BADXML; + prs->uni_char = c & mask; prs->uni_len = 1; if (stack_old == -1 && (prs->context == C_TAG @@ -350,7 +367,7 @@ sax_core (iksparser *prs, char *buf, int len) memset (prs->atts, 0, sizeof(char *) * 2 * 12); prs->attcur = 0; } else { - if (prs->attcur >= (prs->attmax * 2)) { + if (prs->attcur >= ((prs->attmax - 1) * 2)) { void *tmp; prs->attmax += 12; tmp = iks_malloc (sizeof(char *) * 2 * prs->attmax); @@ -375,6 +392,14 @@ sax_core (iksparser *prs, char *buf, int len) prs->context = C_VALUE; break; } + if (IS_WHITESPACE(c)) { + if (stack_old != -1) STACK_PUSH (buf + stack_old, pos - stack_old); + stack_old = -1; + STACK_PUSH_END; + prs->oldcontext = C_ATTRIBUTE_1; + prs->context = C_WHITESPACE; + break; + } if (stack_old == -1) stack_old = pos; break; @@ -396,6 +421,7 @@ sax_core (iksparser *prs, char *buf, int len) break; case C_VALUE: + if (IS_WHITESPACE(c)) break; prs->atts[prs->attcur + 1] = STACK_PUSH_START; if ('\'' == c) { prs->context = C_VALUE_APOS; @@ -622,6 +648,7 @@ iks_parser_reset (iksparser *prs) prs->nr_lines = 0; prs->uni_max = 0; prs->uni_len = 0; + prs->uni_char = 0; } void |