diff options
-rw-r--r-- | src/lj_serialize.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/src/lj_serialize.c b/src/lj_serialize.c index e12e3668..d6551b11 100644 --- a/src/lj_serialize.c +++ b/src/lj_serialize.c | |||
@@ -355,13 +355,13 @@ static char *serialize_get(char *r, SBufExt *sbx, TValue *o) | |||
355 | #if LJ_BE | 355 | #if LJ_BE |
356 | o->u64 = lj_bswap64(o->u64); | 356 | o->u64 = lj_bswap64(o->u64); |
357 | #endif | 357 | #endif |
358 | if (!tvisnum(o)) setnanV(o); | 358 | if (!tvisnum(o)) setnanV(o); /* Fix non-canonical NaNs. */ |
359 | } else if (tp <= SER_TAG_TRUE) { | 359 | } else if (tp <= SER_TAG_TRUE) { |
360 | setpriV(o, ~tp); | 360 | setpriV(o, ~tp); |
361 | } else if (tp == SER_TAG_DICT_STR) { | 361 | } else if (tp == SER_TAG_DICT_STR) { |
362 | GCtab *dict_str; | 362 | GCtab *dict_str; |
363 | uint32_t idx; | 363 | uint32_t idx; |
364 | r = serialize_ru124(r, w, &idx); | 364 | r = serialize_ru124(r, w, &idx); if (LJ_UNLIKELY(!r)) goto eob; |
365 | idx++; | 365 | idx++; |
366 | dict_str = tabref(sbx->dict_str); | 366 | dict_str = tabref(sbx->dict_str); |
367 | if (dict_str && idx < dict_str->asize && tvisstr(arrayslot(dict_str, idx))) | 367 | if (dict_str && idx < dict_str->asize && tvisstr(arrayslot(dict_str, idx))) |
@@ -371,6 +371,8 @@ static char *serialize_get(char *r, SBufExt *sbx, TValue *o) | |||
371 | } else if (tp >= SER_TAG_TAB && tp <= SER_TAG_DICT_MT) { | 371 | } else if (tp >= SER_TAG_TAB && tp <= SER_TAG_DICT_MT) { |
372 | uint32_t narray = 0, nhash = 0; | 372 | uint32_t narray = 0, nhash = 0; |
373 | GCtab *t, *mt = NULL; | 373 | GCtab *t, *mt = NULL; |
374 | if (sbx->depth <= 0) lj_err_caller(sbufL(sbx), LJ_ERR_BUFFER_DEPTH); | ||
375 | sbx->depth--; | ||
374 | if (tp == SER_TAG_DICT_MT) { | 376 | if (tp == SER_TAG_DICT_MT) { |
375 | GCtab *dict_mt; | 377 | GCtab *dict_mt; |
376 | uint32_t idx; | 378 | uint32_t idx; |
@@ -409,6 +411,7 @@ static char *serialize_get(char *r, SBufExt *sbx, TValue *o) | |||
409 | r = serialize_get(r, sbx, v); | 411 | r = serialize_get(r, sbx, v); |
410 | } while (--nhash); | 412 | } while (--nhash); |
411 | } | 413 | } |
414 | sbx->depth++; | ||
412 | #if LJ_HASFFI | 415 | #if LJ_HASFFI |
413 | } else if (tp >= SER_TAG_INT64 && tp <= SER_TAG_COMPLEX) { | 416 | } else if (tp >= SER_TAG_INT64 && tp <= SER_TAG_COMPLEX) { |
414 | uint32_t sz = tp == SER_TAG_COMPLEX ? 16 : 8; | 417 | uint32_t sz = tp == SER_TAG_COMPLEX ? 16 : 8; |
@@ -424,6 +427,11 @@ static char *serialize_get(char *r, SBufExt *sbx, TValue *o) | |||
424 | if (sz == 16) | 427 | if (sz == 16) |
425 | ((uint64_t *)cdataptr(cd))[1] = lj_bswap64(((uint64_t *)cdataptr(cd))[1]); | 428 | ((uint64_t *)cdataptr(cd))[1] = lj_bswap64(((uint64_t *)cdataptr(cd))[1]); |
426 | #endif | 429 | #endif |
430 | if (sz == 16) { /* Fix non-canonical NaNs. */ | ||
431 | TValue *cdo = (TValue *)cdataptr(cd); | ||
432 | if (!tvisnum(&cdo[0])) setnanV(&cdo[0]); | ||
433 | if (!tvisnum(&cdo[1])) setnanV(&cdo[1]); | ||
434 | } | ||
427 | setcdataV(sbufL(sbx), o, cd); | 435 | setcdataV(sbufL(sbx), o, cd); |
428 | #endif | 436 | #endif |
429 | } else if (tp <= (LJ_64 ? SER_TAG_LIGHTUD64 : SER_TAG_LIGHTUD32)) { | 437 | } else if (tp <= (LJ_64 ? SER_TAG_LIGHTUD64 : SER_TAG_LIGHTUD32)) { |
@@ -468,6 +476,7 @@ SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o) | |||
468 | /* Decode from buffer. */ | 476 | /* Decode from buffer. */ |
469 | char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o) | 477 | char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o) |
470 | { | 478 | { |
479 | sbx->depth = LJ_SERIALIZE_DEPTH; | ||
471 | return serialize_get(sbx->r, sbx, o); | 480 | return serialize_get(sbx->r, sbx, o); |
472 | } | 481 | } |
473 | 482 | ||
@@ -491,7 +500,8 @@ void lj_serialize_decode(lua_State *L, TValue *o, GCstr *str) | |||
491 | memset(&sbx, 0, sizeof(SBufExt)); | 500 | memset(&sbx, 0, sizeof(SBufExt)); |
492 | lj_bufx_set_cow(L, &sbx, strdata(str), str->len); | 501 | lj_bufx_set_cow(L, &sbx, strdata(str), str->len); |
493 | /* No need to set sbx.cowref here. */ | 502 | /* No need to set sbx.cowref here. */ |
494 | r = lj_serialize_get(&sbx, o); | 503 | sbx.depth = LJ_SERIALIZE_DEPTH; |
504 | r = serialize_get(sbx.r, &sbx, o); | ||
495 | if (r != sbx.w) lj_err_caller(L, LJ_ERR_BUFFER_LEFTOV); | 505 | if (r != sbx.w) lj_err_caller(L, LJ_ERR_BUFFER_LEFTOV); |
496 | } | 506 | } |
497 | 507 | ||