static tr_variant* get_node (tr_ptrArray * stack, tr_quark * key, tr_variant * top, int * err) { tr_variant * node = NULL; if (tr_ptrArrayEmpty (stack)) { node = top; } else { tr_variant * parent = tr_ptrArrayBack (stack); if (tr_variantIsList (parent)) { node = tr_variantListAdd (parent); } else if (*key && tr_variantIsDict (parent)) { node = tr_variantDictAdd (parent, *key); *key = 0; } else { *err = EILSEQ; } } return node; }
static tr_benc* get_node (struct jsonsl_st * jsn) { tr_benc * parent; tr_benc * node = NULL; struct json_wrapper_data * data = jsn->data; parent = tr_ptrArrayEmpty (&data->stack) ? NULL : tr_ptrArrayBack (&data->stack); if (!parent) { node = data->top; } else if (tr_bencIsList (parent)) { node = tr_bencListAdd (parent); } else if (tr_bencIsDict (parent) && (data->key!=NULL)) { node = tr_bencDictAdd (parent, data->key); tr_free (data->key); data->key = NULL; } return node; }
static tr_variant* get_node (struct jsonsl_st * jsn) { tr_variant * parent; tr_variant * node = NULL; struct json_wrapper_data * data = jsn->data; parent = tr_ptrArrayEmpty (&data->stack) ? NULL : tr_ptrArrayBack (&data->stack); if (!parent) { node = data->top; } else if (tr_variantIsList (parent)) { node = tr_variantListAdd (parent); } else if (tr_variantIsDict (parent) && (data->key!=NULL)) { node = tr_variantDictAdd (parent, tr_quark_new (data->key, data->keylen)); data->key = NULL; data->keylen = 0; } return node; }
static tr_benc* getNode( struct json_benc_data * data ) { tr_benc * parent; tr_benc * node = NULL; if( tr_ptrArrayEmpty( data->stack ) ) parent = NULL; else parent = tr_ptrArrayBack( data->stack ); if( !parent ) node = data->top; else if( tr_bencIsList( parent ) ) node = tr_bencListAdd( parent ); else if( tr_bencIsDict( parent ) && data->key ) { node = tr_bencDictAdd( parent, data->key ); tr_free( data->key ); data->key = NULL; } return node; }
/** * This function's previous recursive implementation was * easier to read, but was vulnerable to a smash-stacking * attack via maliciously-crafted bencoded data. (#667) */ int tr_variantParseBenc (const void * buf_in, const void * bufend_in, tr_variant * top, const char ** setme_end) { int err = 0; const uint8_t * buf = buf_in; const uint8_t * bufend = bufend_in; tr_ptrArray stack = TR_PTR_ARRAY_INIT; tr_quark key = 0; tr_variantInit (top, 0); while (buf != bufend) { if (buf > bufend) /* no more text to parse... */ err = EILSEQ; if (err) break; if (*buf == 'i') /* int */ { int64_t val; const uint8_t * end; tr_variant * v; if ((err = tr_bencParseInt (buf, bufend, &end, &val))) break; buf = end; if ((v = get_node (&stack, &key, top, &err))) tr_variantInitInt (v, val); } else if (*buf == 'l') /* list */ { tr_variant * v; ++buf; if ((v = get_node (&stack, &key, top, &err))) { tr_variantInitList (v, 0); tr_ptrArrayAppend (&stack, v); } } else if (*buf == 'd') /* dict */ { tr_variant * v; ++buf; if ((v = get_node (&stack, &key, top, &err))) { tr_variantInitDict (v, 0); tr_ptrArrayAppend (&stack, v); } } else if (*buf == 'e') /* end of list or dict */ { ++buf; if (tr_ptrArrayEmpty (&stack) || (key != 0)) { err = EILSEQ; break; } else { tr_ptrArrayPop (&stack); if (tr_ptrArrayEmpty (&stack)) break; } } else if (isdigit (*buf)) /* string? */ { tr_variant * v; const uint8_t * end; const uint8_t * str; size_t str_len; if ((err = tr_bencParseStr (buf, bufend, &end, &str, &str_len))) break; buf = end; if (!key && !tr_ptrArrayEmpty(&stack) && tr_variantIsDict(tr_ptrArrayBack(&stack))) key = tr_quark_new (str, str_len); else if ((v = get_node (&stack, &key, top, &err))) tr_variantInitStr (v, str, str_len); } else /* invalid bencoded text... march past it */ { ++buf; } if (tr_ptrArrayEmpty (&stack)) break; } if (!err && (!top->type || !tr_ptrArrayEmpty(&stack))) err = EILSEQ; if (!err && setme_end) *setme_end = (const char*) buf; tr_ptrArrayDestruct (&stack, NULL); return err; }