tag 547683 patch thanks Hi,
The attached patch makes totem-pl-parser reentrant. Rhythmbox hasn't crashed during the (admittedly short) time I've been using it, even when I forced it to reload all of the podcasts I'm subscribed to multiple times. -- Matt Kraai http://ftbfs.org/
only in patch2: unchanged: --- totem-pl-parser-2.28.1.orig/plparse/xmllexer.h +++ totem-pl-parser-2.28.1/plparse/xmllexer.h @@ -51,9 +51,26 @@ #define T_CDATA_STOP 19 /* ]]> */ +/* public structures */ +struct lexer +{ + const char * lexbuf; + int lexbuf_size; + int lexbuf_pos; + int in_comment; + char * lex_malloc; + enum { + NORMAL, + DATA, + CDATA, + } lex_mode; +}; + + /* public functions */ -void lexer_init(const char * buf, int size) XINE_PROTECTED; -int lexer_get_token(char * tok, int tok_size) XINE_PROTECTED; +struct lexer *lexer_init(const char * buf, int size) XINE_PROTECTED; +void lexer_finalize(struct lexer * lexer) XINE_PROTECTED; +int lexer_get_token(struct lexer * lexer, char * tok, int tok_size) XINE_PROTECTED; char *lexer_decode_entities (const char *tok) XINE_PROTECTED; #endif only in patch2: unchanged: --- totem-pl-parser-2.28.1.orig/plparse/xmlparser.c +++ totem-pl-parser-2.28.1/plparse/xmlparser.c @@ -51,9 +51,6 @@ #define DATA_SIZE 64 * 1024 #define MAX_RECURSION 23 -/* private global variables */ -static int xml_parser_mode; - /* private functions */ static char * strtoupper(char * str) { @@ -103,10 +100,17 @@ free(property); } -void xml_parser_init(const char * buf, int size, int mode) { +xml_parser_t *xml_parser_init(const char * buf, int size, int mode) { + xml_parser_t *xml_parser = malloc(sizeof(xml_parser_t)); + xml_parser->lexer = lexer_init(buf, size); + xml_parser->mode = mode; + return xml_parser; +} - lexer_init(buf, size); - xml_parser_mode = mode; +void xml_parser_finalize(xml_parser_t *xml_parser) +{ + lexer_finalize(xml_parser->lexer); + free(xml_parser); } static void xml_parser_free_props(xml_property_t *current_property) { @@ -220,7 +224,7 @@ #define Q_STATE(CURRENT,NEW) (STATE_##NEW + state - STATE_##CURRENT) -static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_names[], int rec, int flags) +static int xml_parser_get_node_internal (xml_parser_t *xml_parser, xml_node_t *current_node, char *root_names[], int rec, int flags) { char tok[TOKEN_SIZE]; char property_name[TOKEN_SIZE]; @@ -239,7 +243,7 @@ memset (tok, 0, TOKEN_SIZE); - while ((bypass_get_token) || (res = lexer_get_token(tok, TOKEN_SIZE)) != T_ERROR) { + while ((bypass_get_token) || (res = lexer_get_token(xml_parser->lexer, tok, TOKEN_SIZE)) != T_ERROR) { bypass_get_token = 0; lprintf("info: %d - %d : '%s'\n", state, res, tok); @@ -295,7 +299,7 @@ current_property = NULL; /* save node name */ - if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { + if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } if (state == STATE_Q_NODE) { @@ -331,7 +335,7 @@ subtree->props = properties; lprintf("info: rec %d new subtree %s\n", rec, node_name); root_names[rec + 1] = node_name; - parse_res = xml_parser_get_node_internal(subtree, root_names, rec + 1, flags); + parse_res = xml_parser_get_node_internal(xml_parser, subtree, root_names, rec + 1, flags); if (parse_res == -1 || parse_res > 0) { return parse_res; } @@ -374,7 +378,7 @@ case (T_IDENT): /* save property name */ new_prop: - if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { + if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } strcpy(property_name, tok); @@ -409,7 +413,7 @@ switch (res) { case (T_IDENT): /* must be equal to root_name */ - if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { + if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } if (strcmp(tok, root_names[rec]) == 0) { @@ -621,19 +625,19 @@ } } -static int xml_parser_get_node (xml_node_t *current_node, int flags) +static int xml_parser_get_node (xml_parser_t *xml_parser, xml_node_t *current_node, int flags) { char *root_names[MAX_RECURSION + 1]; root_names[0] = ""; - return xml_parser_get_node_internal (current_node, root_names, 0, flags); + return xml_parser_get_node_internal (xml_parser, current_node, root_names, 0, flags); } -int xml_parser_build_tree_with_options(xml_node_t **root_node, int flags) { +int xml_parser_build_tree_with_options(xml_parser_t *xml_parser, xml_node_t **root_node, int flags) { xml_node_t *tmp_node, *pri_node, *q_node; int res; tmp_node = new_xml_node(); - res = xml_parser_get_node(tmp_node, flags); + res = xml_parser_get_node(xml_parser, tmp_node, flags); /* delete any top-level [CDATA] nodes */; pri_node = tmp_node->child; @@ -676,8 +680,8 @@ return res; } -int xml_parser_build_tree(xml_node_t **root_node) { - return xml_parser_build_tree_with_options (root_node, 0); +int xml_parser_build_tree(xml_parser_t *xml_parser, xml_node_t **root_node) { + return xml_parser_build_tree_with_options (xml_parser, root_node, 0); } const char *xml_parser_get_property (const xml_node_t *node, const char *name) { only in patch2: unchanged: --- totem-pl-parser-2.28.1.orig/plparse/totem-pl-parser.c +++ totem-pl-parser-2.28.1/plparse/totem-pl-parser.c @@ -1676,11 +1676,16 @@ xml_node_t* doc, *node; char *encoding, *new_contents; gsize new_size; + xml_parser_t *xml_parser; totem_pl_parser_cleanup_xml (contents); - xml_parser_init (contents, size, XML_PARSER_CASE_INSENSITIVE); - if (xml_parser_build_tree_with_options (&doc, XML_PARSER_RELAXED | XML_PARSER_MULTI_TEXT) < 0) + xml_parser = xml_parser_init (contents, size, XML_PARSER_CASE_INSENSITIVE); + if (xml_parser_build_tree_with_options (xml_parser, &doc, XML_PARSER_RELAXED | XML_PARSER_MULTI_TEXT) < 0) { + xml_parser_finalize (xml_parser); return NULL; + } + + xml_parser_finalize (xml_parser); encoding = NULL; for (node = doc; node != NULL; node = node->next) { @@ -1705,12 +1710,14 @@ } g_free (encoding); - xml_parser_init (new_contents, new_size, XML_PARSER_CASE_INSENSITIVE); - if (xml_parser_build_tree_with_options (&doc, XML_PARSER_RELAXED | XML_PARSER_MULTI_TEXT) < 0) { + xml_parser = xml_parser_init (new_contents, new_size, XML_PARSER_CASE_INSENSITIVE); + if (xml_parser_build_tree_with_options (xml_parser, &doc, XML_PARSER_RELAXED | XML_PARSER_MULTI_TEXT) < 0) { + xml_parser_finalize (xml_parser); g_free (new_contents); return NULL; } + xml_parser_finalize (xml_parser); g_free (new_contents); return doc; only in patch2: unchanged: --- totem-pl-parser-2.28.1.orig/plparse/xmlparser.h +++ totem-pl-parser-2.28.1/plparse/xmlparser.h @@ -65,10 +65,16 @@ struct xml_node_s *next; } xml_node_t; -void xml_parser_init(const char * buf, int size, int mode) XINE_PROTECTED; +typedef struct xml_parser_s { + struct lexer *lexer; + int mode; +} xml_parser_t; -int xml_parser_build_tree(xml_node_t **root_node) XINE_PROTECTED; -int xml_parser_build_tree_with_options(xml_node_t **root_node, int flags) XINE_PROTECTED; +xml_parser_t *xml_parser_init(const char * buf, int size, int mode) XINE_PROTECTED; +void xml_parser_finalize(xml_parser_t *xml_parser) XINE_PROTECTED; + +int xml_parser_build_tree(xml_parser_t *xml_parser, xml_node_t **root_node) XINE_PROTECTED; +int xml_parser_build_tree_with_options(xml_parser_t *xml_parser, xml_node_t **root_node, int flags) XINE_PROTECTED; void xml_parser_free_tree(xml_node_t *root_node) XINE_PROTECTED; only in patch2: unchanged: --- totem-pl-parser-2.28.1.orig/plparse/xmllexer.c +++ totem-pl-parser-2.28.1/plparse/xmllexer.c @@ -44,16 +44,9 @@ /* private constants*/ -/* private global variables */ -static const char * lexbuf; -static int lexbuf_size = 0; -static int lexbuf_pos = 0; -static int in_comment = 0; -static char *lex_malloc = NULL; - enum utf { UTF32BE, UTF32LE, UTF16BE, UTF16LE }; -static void lex_convert (const char * buf, int size, enum utf utf) +static void lex_convert (struct lexer * lexer, const char * buf, int size, enum utf utf) { char *utf8 = malloc (size * (utf >= UTF16BE ? 3 : 6) + 1); char *bp = utf8; @@ -85,45 +78,44 @@ } } *bp = 0; - lexbuf_size = bp - utf8; - lexbuf = lex_malloc = realloc (utf8, lexbuf_size + 1); + lexer->lexbuf_size = bp - utf8; + lexer->lexbuf = lexer->lex_malloc = realloc (utf8, lexer->lexbuf_size + 1); } -static enum { - NORMAL, - DATA, - CDATA, -} lex_mode = NORMAL; - -void lexer_init(const char * buf, int size) { +struct lexer *lexer_init(const char * buf, int size) { static const char boms[] = { 0xFF, 0xFE, 0, 0, 0xFE, 0xFF }, bom_utf8[] = { 0xEF, 0xBB, 0xBF }; + struct lexer * lexer = calloc (1, sizeof (*lexer)); - free (lex_malloc); - lex_malloc = NULL; - - lexbuf = buf; - lexbuf_size = size; + lexer->lexbuf = buf; + lexer->lexbuf_size = size; if (size >= 4 && !memcmp (buf, boms + 2, 4)) - lex_convert (buf + 4, size - 4, UTF32BE); + lex_convert (lexer, buf + 4, size - 4, UTF32BE); else if (size >= 4 && !memcmp (buf, boms, 4)) - lex_convert (buf + 4, size - 4, UTF32LE); + lex_convert (lexer, buf + 4, size - 4, UTF32LE); else if (size >= 3 && !memcmp (buf, bom_utf8, 3)) { - lexbuf += 3; - lexbuf_size -= 3; + lexer->lexbuf += 3; + lexer->lexbuf_size -= 3; } else if (size >= 2 && !memcmp (buf, boms + 4, 2)) - lex_convert (buf + 2, size - 2, UTF16BE); + lex_convert (lexer, buf + 2, size - 2, UTF16BE); else if (size >= 2 && !memcmp (buf, boms, 2)) - lex_convert (buf + 2, size - 2, UTF16LE); + lex_convert (lexer, buf + 2, size - 2, UTF16LE); - lexbuf_pos = 0; - lex_mode = NORMAL; - in_comment = 0; + lexer->lexbuf_pos = 0; + lexer->lex_mode = NORMAL; + lexer->in_comment = 0; lprintf("buffer length %d\n", size); + return lexer; +} + +void lexer_finalize(struct lexer * lexer) +{ + free (lexer->lex_malloc); + free (lexer); } typedef enum { @@ -144,17 +136,17 @@ STATE_IDENT /* must be last */ } lexer_state_t; -int lexer_get_token(char * tok, int tok_size) { +int lexer_get_token(struct lexer * lexer, char * tok, int tok_size) { int tok_pos = 0; lexer_state_t state = STATE_IDLE; char c; if (tok) { - while ((tok_pos < tok_size) && (lexbuf_pos < lexbuf_size)) { - c = lexbuf[lexbuf_pos]; - lprintf("c=%c, state=%d, lex_mode=%d, in_comment=%d\n", c, state, lex_mode, in_comment); + while ((tok_pos < tok_size) && (lexer->lexbuf_pos < lexer->lexbuf_size)) { + c = lexer->lexbuf[lexer->lexbuf_pos]; + lprintf("c=%c, state=%d, lex_mode=%d, lexer->in_comment=%d\n", c, state, lexer->lex_mode, lexer->in_comment); - switch (lex_mode) { + switch (lexer->lex_mode) { case NORMAL: switch (state) { /* init state */ @@ -187,7 +179,7 @@ break; case '/': - if (!in_comment) + if (!lexer->in_comment) state = STATE_T_M_STOP_2; tok[tok_pos] = c; tok_pos++; @@ -214,7 +206,7 @@ break; case '?': - if (!in_comment) + if (!lexer->in_comment) state = STATE_T_TI_STOP; tok[tok_pos] = c; tok_pos++; @@ -226,14 +218,14 @@ tok_pos++; break; } - lexbuf_pos++; + lexer->lexbuf_pos++; break; /* end of line */ case STATE_EOL: if (c == '\n' || (c == '\r')) { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; } else { tok[tok_pos] = '\0'; @@ -245,7 +237,7 @@ case STATE_SEPAR: if (c == ' ' || (c == '\t')) { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; } else { tok[tok_pos] = '\0'; @@ -258,20 +250,20 @@ switch (c) { case '/': tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; return T_M_START_2; break; case '!': tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; state = STATE_T_COMMENT; break; case '?': tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; return T_TI_START; @@ -285,8 +277,8 @@ /* T_M_STOP_1 */ case STATE_T_M_STOP_1: tok[tok_pos] = '\0'; - if (!in_comment) - lex_mode = DATA; + if (!lexer->in_comment) + lexer->lex_mode = DATA; return T_M_STOP_1; break; @@ -294,11 +286,11 @@ case STATE_T_M_STOP_2: if (c == '>') { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; - if (!in_comment) - lex_mode = DATA; + if (!lexer->in_comment) + lexer->lex_mode = DATA; return T_M_STOP_2; } else { tok[tok_pos] = '\0'; @@ -315,7 +307,7 @@ /* T_STRING */ case STATE_T_STRING_DOUBLE: tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; if (c == '\"') { /* " */ tok[tok_pos] = '\0'; /* FIXME */ return T_STRING; @@ -327,33 +319,33 @@ case STATE_T_COMMENT: switch (c) { case '-': - lexbuf_pos++; - if (lexbuf[lexbuf_pos] == '-') + lexer->lexbuf_pos++; + if (lexer->lexbuf[lexer->lexbuf_pos] == '-') { - lexbuf_pos++; + lexer->lexbuf_pos++; tok[tok_pos++] = '-'; /* FIXME */ tok[tok_pos++] = '-'; tok[tok_pos] = '\0'; - in_comment = 1; + lexer->in_comment = 1; return T_C_START; } break; case 'D': - lexbuf_pos++; - if (strncmp(lexbuf + lexbuf_pos, "OCTYPE", 6) == 0) { + lexer->lexbuf_pos++; + if (strncmp(lexer->lexbuf + lexer->lexbuf_pos, "OCTYPE", 6) == 0) { strncpy(tok + tok_pos, "DOCTYPE", 7); /* FIXME */ - lexbuf_pos += 6; + lexer->lexbuf_pos += 6; return T_DOCTYPE_START; } else { return T_ERROR; } break; case '[': - lexbuf_pos++; - if (strncmp(lexbuf + lexbuf_pos, "CDATA[", 6) == 0) { + lexer->lexbuf_pos++; + if (strncmp(lexer->lexbuf + lexer->lexbuf_pos, "CDATA[", 6) == 0) { strncpy (tok + tok_pos, "[CDATA[", 7); /* FIXME */ - lexbuf_pos += 6; - lex_mode = CDATA; + lexer->lexbuf_pos += 6; + lexer->lex_mode = CDATA; return T_CDATA_START; } else{ return T_ERROR; @@ -369,11 +361,11 @@ case STATE_T_TI_STOP: if (c == '>') { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; - if (!in_comment) - lex_mode = DATA; + if (!lexer->in_comment) + lexer->lex_mode = DATA; return T_TI_STOP; } else { tok[tok_pos] = '\0'; @@ -387,13 +379,13 @@ case '-': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = STATE_T_C_STOP; break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = STATE_IDENT; } break; @@ -404,21 +396,21 @@ case '>': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; tok[tok_pos] = '\0'; /* FIX ME */ if (strlen(tok) != 3) { tok[tok_pos - 3] = '\0'; - lexbuf_pos -= 3; + lexer->lexbuf_pos -= 3; return T_IDENT; } else { - in_comment = 0; + lexer->in_comment = 0; return T_C_STOP; } break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = STATE_IDENT; } break; @@ -426,7 +418,7 @@ /* T_STRING (single quotes) */ case STATE_T_STRING_SINGLE: tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; if (c == '\'') { /* " */ tok[tok_pos] = '\0'; /* FIXME */ return T_STRING; @@ -453,19 +445,19 @@ case '?': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = STATE_T_TI_STOP; break; case '-': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = STATE_T_DASHDASH; break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; } break; default: @@ -479,12 +471,12 @@ { case '<': tok[tok_pos] = '\0'; - lex_mode = NORMAL; + lexer->lex_mode = NORMAL; return T_DATA; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; } break; @@ -492,32 +484,32 @@ switch (c) { case ']': - if (strncmp(lexbuf + lexbuf_pos, "]]>", 3) == 0) { - lexbuf_pos += 3; - lex_mode = DATA; + if (strncmp(lexer->lexbuf + lexer->lexbuf_pos, "]]>", 3) == 0) { + lexer->lexbuf_pos += 3; + lexer->lex_mode = DATA; return T_CDATA_STOP; } else { tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; } break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; } break; } } lprintf ("loop done tok_pos = %d, tok_size=%d, lexbuf_pos=%d, lexbuf_size=%d\n", - tok_pos, tok_size, lexbuf_pos, lexbuf_size); + tok_pos, tok_size, lexer->lexbuf_pos, lexer->lexbuf_size); /* pb */ if (tok_pos >= tok_size) { lprintf("token buffer is too little\n"); } else { - if (lexbuf_pos >= lexbuf_size) { + if (lexer->lexbuf_pos >= lexer->lexbuf_size) { /* Terminate the current token */ tok[tok_pos] = '\0'; switch (state) {