--- JSON-XS/XS.xs 2016/02/21 16:18:19 1.126 +++ JSON-XS/XS.xs 2016/11/16 18:06:34 1.129 @@ -320,7 +320,6 @@ return 1; else if (*pv == '0') return 0; - } return -1; @@ -335,11 +334,14 @@ scalar = SvRV (scalar); - if (SvSTASH (scalar) == bool_stash) - return 1; + if (SvTYPE (scalar) >= SVt_PVMG) + { + if (SvSTASH (scalar) == bool_stash) + return 1; - if (!SvOBJECT (scalar) && ref_bool_type (scalar) >= 0) - return 1; + if (!SvOBJECT (scalar) && ref_bool_type (scalar) >= 0) + return 1; + } return 0; } @@ -1689,7 +1691,7 @@ } static SV * -decode_json (SV *string, JSON *json, char **offset_return) +decode_json (SV *string, JSON *json, STRLEN *offset_return) { dec_t dec; SV *sv; @@ -1698,9 +1700,12 @@ * makes perl ignore the magic in subsequent accesses. * also make a copy of non-PV values, to get them into a clean * state (SvPV should do that, but it's buggy, see below). + * + * SvIsCOW_shared_hash works around a bug in perl (possibly 5.16), + * as reported by Reini Urban. */ /*SvGETMAGIC (string);*/ - if (SvMAGICAL (string) || !SvPOK (string)) + if (SvMAGICAL (string) || !SvPOK (string) || SvIsCOW_shared_hash (string)) string = sv_2mortal (newSVsv (string)); SvUPGRADE (string, SVt_PV); @@ -1749,9 +1754,8 @@ sv = decode_sv (&dec); if (offset_return) - *offset_return = dec.cur; - - if (!(offset_return || !sv)) + *offset_return = dec.cur - SvPVX (string); + else if (sv) { // check for trailing garbage decode_ws (&dec); @@ -2108,11 +2112,11 @@ PPCODE: { SV *sv; - char *offset; + STRLEN offset; PUTBACK; sv = decode_json (jsonstr, self, &offset); SPAGAIN; EXTEND (SP, 2); PUSHs (sv); - PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, offset)))); + PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, SvPV_nolen (jsonstr) + offset)))); } void incr_parse (JSON *self, SV *jsonstr = 0) @@ -2169,7 +2173,7 @@ do { SV *sv; - char *offset; + STRLEN offset; if (!INCR_DONE (self)) { @@ -2195,11 +2199,11 @@ PUTBACK; sv = decode_json (self->incr_text, self, &offset); SPAGAIN; XPUSHs (sv); - self->incr_pos -= offset - SvPVX (self->incr_text); + self->incr_pos -= offset; self->incr_nest = 0; self->incr_mode = 0; - sv_chop (self->incr_text, offset); + sv_chop (self->incr_text, SvPVX (self->incr_text) + offset); } while (GIMME_V == G_ARRAY); }