ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/JSON-XS/XS.xs
(Generate patch)

Comparing JSON-XS/XS.xs (file contents):
Revision 1.126 by root, Sun Feb 21 16:18:19 2016 UTC vs.
Revision 1.132 by root, Tue Sep 5 13:07:09 2017 UTC

6#include <string.h> 6#include <string.h>
7#include <stdlib.h> 7#include <stdlib.h>
8#include <stdio.h> 8#include <stdio.h>
9#include <limits.h> 9#include <limits.h>
10#include <float.h> 10#include <float.h>
11#include <inttypes.h>
11 12
12#if defined(__BORLANDC__) || defined(_MSC_VER) 13#if defined(__BORLANDC__) || defined(_MSC_VER)
13# define snprintf _snprintf // C compilers have this in stdio.h 14# define snprintf _snprintf // C compilers have this in stdio.h
14#endif 15#endif
15 16
154 SvPV_renew (sv, SvCUR (sv) + 1); 155 SvPV_renew (sv, SvCUR (sv) + 1);
155#endif 156#endif
156 } 157 }
157} 158}
158 159
160/* adds two STRLENs together, slow, and with paranoia */
161STRLEN
162strlen_sum (STRLEN l1, STRLEN l2)
163{
164 size_t sum = l1 + l2;
165
166 if (sum < (size_t)l2 || sum != (size_t)(STRLEN)sum)
167 croak ("JSON::XS: string size overflow");
168
169 return sum;
170}
171
172/* similar to SvGROW, but somewhat safer and guarantees exponential realloc strategy */
173static char *
174json_sv_grow (SV *sv, size_t len1, size_t len2)
175{
176 len1 = strlen_sum (len1, len2);
177 len1 = strlen_sum (len1, len1 >> 1);
178
179 if (len1 > 4096 - 24)
180 len1 = (len1 | 4095) - 24;
181
182 return SvGROW (sv, len1);
183}
184
159// decode an utf-8 character and return it, or (UV)-1 in 185// decode a utf-8 character and return it, or (UV)-1 in
160// case of an error. 186// case of an error.
161// we special-case "safe" characters from U+80 .. U+7FF, 187// we special-case "safe" characters from U+80 .. U+7FF,
162// but use the very good perl function to parse anything else. 188// but use the very good perl function to parse anything else.
163// note that we never call this function for a ascii codepoints 189// note that we never call this function for a ascii codepoints
164INLINE UV 190INLINE UV
318 if (len == 1) 344 if (len == 1)
319 if (*pv == '1') 345 if (*pv == '1')
320 return 1; 346 return 1;
321 else if (*pv == '0') 347 else if (*pv == '0')
322 return 0; 348 return 0;
323
324 } 349 }
325 350
326 return -1; 351 return -1;
327} 352}
328 353
333 if (!SvROK (scalar)) 358 if (!SvROK (scalar))
334 return 1; 359 return 1;
335 360
336 scalar = SvRV (scalar); 361 scalar = SvRV (scalar);
337 362
363 if (SvTYPE (scalar) >= SVt_PVMG)
364 {
338 if (SvSTASH (scalar) == bool_stash) 365 if (SvSTASH (scalar) == bool_stash)
339 return 1; 366 return 1;
340 367
341 if (!SvOBJECT (scalar) && ref_bool_type (scalar) >= 0) 368 if (!SvOBJECT (scalar) && ref_bool_type (scalar) >= 0)
342 return 1; 369 return 1;
370 }
343 371
344 return 0; 372 return 0;
345} 373}
346 374
347///////////////////////////////////////////////////////////////////////////// 375/////////////////////////////////////////////////////////////////////////////
359} enc_t; 387} enc_t;
360 388
361INLINE void 389INLINE void
362need (enc_t *enc, STRLEN len) 390need (enc_t *enc, STRLEN len)
363{ 391{
364 if (expect_false (enc->cur + len >= enc->end)) 392 if (expect_false ((uintptr_t)(enc->end - enc->cur) < len))
365 { 393 {
366 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv); 394 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv);
367 SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 395 char *buf = json_sv_grow (enc->sv, cur, len);
368 enc->cur = SvPVX (enc->sv) + cur; 396 enc->cur = buf + cur;
369 enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1; 397 enc->end = buf + SvLEN (enc->sv) - 1;
370 } 398 }
371} 399}
372 400
373INLINE void 401INLINE void
374encode_ch (enc_t *enc, char ch) 402encode_ch (enc_t *enc, char ch)
390 418
391 if (expect_true (ch >= 0x20 && ch < 0x80)) // most common case 419 if (expect_true (ch >= 0x20 && ch < 0x80)) // most common case
392 { 420 {
393 if (expect_false (ch == '"')) // but with slow exceptions 421 if (expect_false (ch == '"')) // but with slow exceptions
394 { 422 {
395 need (enc, len += 1); 423 need (enc, len + 1);
396 *enc->cur++ = '\\'; 424 *enc->cur++ = '\\';
397 *enc->cur++ = '"'; 425 *enc->cur++ = '"';
398 } 426 }
399 else if (expect_false (ch == '\\')) 427 else if (expect_false (ch == '\\'))
400 { 428 {
401 need (enc, len += 1); 429 need (enc, len + 1);
402 *enc->cur++ = '\\'; 430 *enc->cur++ = '\\';
403 *enc->cur++ = '\\'; 431 *enc->cur++ = '\\';
404 } 432 }
405 else 433 else
406 *enc->cur++ = ch; 434 *enc->cur++ = ch;
409 } 437 }
410 else 438 else
411 { 439 {
412 switch (ch) 440 switch (ch)
413 { 441 {
414 case '\010': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 'b'; ++str; break; 442 case '\010': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 'b'; ++str; break;
415 case '\011': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 't'; ++str; break; 443 case '\011': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 't'; ++str; break;
416 case '\012': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 'n'; ++str; break; 444 case '\012': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 'n'; ++str; break;
417 case '\014': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 'f'; ++str; break; 445 case '\014': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 'f'; ++str; break;
418 case '\015': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 'r'; ++str; break; 446 case '\015': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 'r'; ++str; break;
419 447
420 default: 448 default:
421 { 449 {
422 STRLEN clen; 450 STRLEN clen;
423 UV uch; 451 UV uch;
439 if (uch >= 0x10000UL) 467 if (uch >= 0x10000UL)
440 { 468 {
441 if (uch >= 0x110000UL) 469 if (uch >= 0x110000UL)
442 croak ("out of range codepoint (0x%lx) encountered, unrepresentable in JSON", (unsigned long)uch); 470 croak ("out of range codepoint (0x%lx) encountered, unrepresentable in JSON", (unsigned long)uch);
443 471
444 need (enc, len += 11); 472 need (enc, len + 11);
445 sprintf (enc->cur, "\\u%04x\\u%04x", 473 sprintf (enc->cur, "\\u%04x\\u%04x",
446 (int)((uch - 0x10000) / 0x400 + 0xD800), 474 (int)((uch - 0x10000) / 0x400 + 0xD800),
447 (int)((uch - 0x10000) % 0x400 + 0xDC00)); 475 (int)((uch - 0x10000) % 0x400 + 0xDC00));
448 enc->cur += 12; 476 enc->cur += 12;
449 } 477 }
450 else 478 else
451 { 479 {
452 need (enc, len += 5); 480 need (enc, len + 5);
453 *enc->cur++ = '\\'; 481 *enc->cur++ = '\\';
454 *enc->cur++ = 'u'; 482 *enc->cur++ = 'u';
455 *enc->cur++ = PL_hexdigit [ uch >> 12 ]; 483 *enc->cur++ = PL_hexdigit [ uch >> 12 ];
456 *enc->cur++ = PL_hexdigit [(uch >> 8) & 15]; 484 *enc->cur++ = PL_hexdigit [(uch >> 8) & 15];
457 *enc->cur++ = PL_hexdigit [(uch >> 4) & 15]; 485 *enc->cur++ = PL_hexdigit [(uch >> 4) & 15];
465 *enc->cur++ = uch; 493 *enc->cur++ = uch;
466 str += clen; 494 str += clen;
467 } 495 }
468 else if (is_utf8) 496 else if (is_utf8)
469 { 497 {
470 need (enc, len += clen); 498 need (enc, len + clen);
471 do 499 do
472 { 500 {
473 *enc->cur++ = *str++; 501 *enc->cur++ = *str++;
474 } 502 }
475 while (--clen); 503 while (--clen);
476 } 504 }
477 else 505 else
478 { 506 {
479 need (enc, len += UTF8_MAXBYTES - 1); // never more than 11 bytes needed 507 need (enc, len + UTF8_MAXBYTES - 1); // never more than 11 bytes needed
480 enc->cur = encode_utf8 (enc->cur, uch); 508 enc->cur = encode_utf8 (enc->cur, uch);
481 ++str; 509 ++str;
482 } 510 }
483 } 511 }
484 } 512 }
1165 1193
1166 if (sv) 1194 if (sv)
1167 { 1195 {
1168 STRLEN cur = SvCUR (sv); 1196 STRLEN cur = SvCUR (sv);
1169 1197
1170 if (SvLEN (sv) <= cur + len) 1198 if (SvLEN (sv) - cur <= len)
1171 SvGROW (sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 1199 json_sv_grow (sv, cur, len);
1172 1200
1173 memcpy (SvPVX (sv) + SvCUR (sv), buf, len); 1201 memcpy (SvPVX (sv) + SvCUR (sv), buf, len);
1174 SvCUR_set (sv, SvCUR (sv) + len); 1202 SvCUR_set (sv, SvCUR (sv) + len);
1175 } 1203 }
1176 else 1204 else
1687fail: 1715fail:
1688 return 0; 1716 return 0;
1689} 1717}
1690 1718
1691static SV * 1719static SV *
1692decode_json (SV *string, JSON *json, char **offset_return) 1720decode_json (SV *string, JSON *json, STRLEN *offset_return)
1693{ 1721{
1694 dec_t dec; 1722 dec_t dec;
1695 SV *sv; 1723 SV *sv;
1696 1724
1697 /* work around bugs in 5.10 where manipulating magic values 1725 /* work around bugs in 5.10 where manipulating magic values
1698 * makes perl ignore the magic in subsequent accesses. 1726 * makes perl ignore the magic in subsequent accesses.
1699 * also make a copy of non-PV values, to get them into a clean 1727 * also make a copy of non-PV values, to get them into a clean
1700 * state (SvPV should do that, but it's buggy, see below). 1728 * state (SvPV should do that, but it's buggy, see below).
1729 *
1730 * SvIsCOW_shared_hash works around a bug in perl (possibly 5.16),
1731 * as reported by Reini Urban.
1701 */ 1732 */
1702 /*SvGETMAGIC (string);*/ 1733 /*SvGETMAGIC (string);*/
1703 if (SvMAGICAL (string) || !SvPOK (string)) 1734 if (SvMAGICAL (string) || !SvPOK (string) || SvIsCOW_shared_hash (string))
1704 string = sv_2mortal (newSVsv (string)); 1735 string = sv_2mortal (newSVsv (string));
1705 1736
1706 SvUPGRADE (string, SVt_PV); 1737 SvUPGRADE (string, SVt_PV);
1707 1738
1708 /* work around a bug in perl 5.10, which causes SvCUR to fail an 1739 /* work around a bug in perl 5.10, which causes SvCUR to fail an
1747 1778
1748 decode_ws (&dec); 1779 decode_ws (&dec);
1749 sv = decode_sv (&dec); 1780 sv = decode_sv (&dec);
1750 1781
1751 if (offset_return) 1782 if (offset_return)
1752 *offset_return = dec.cur; 1783 *offset_return = dec.cur - SvPVX (string);
1753 1784 else if (sv)
1754 if (!(offset_return || !sv))
1755 { 1785 {
1756 // check for trailing garbage 1786 // check for trailing garbage
1757 decode_ws (&dec); 1787 decode_ws (&dec);
1758 1788
1759 if (*dec.cur) 1789 if (*dec.cur)
2106 2136
2107void decode_prefix (JSON *self, SV *jsonstr) 2137void decode_prefix (JSON *self, SV *jsonstr)
2108 PPCODE: 2138 PPCODE:
2109{ 2139{
2110 SV *sv; 2140 SV *sv;
2111 char *offset; 2141 STRLEN offset;
2112 PUTBACK; sv = decode_json (jsonstr, self, &offset); SPAGAIN; 2142 PUTBACK; sv = decode_json (jsonstr, self, &offset); SPAGAIN;
2113 EXTEND (SP, 2); 2143 EXTEND (SP, 2);
2114 PUSHs (sv); 2144 PUSHs (sv);
2115 PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, offset)))); 2145 PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, SvPV_nolen (jsonstr) + offset))));
2116} 2146}
2117 2147
2118void incr_parse (JSON *self, SV *jsonstr = 0) 2148void incr_parse (JSON *self, SV *jsonstr = 0)
2119 PPCODE: 2149 PPCODE:
2120{ 2150{
2154 { 2184 {
2155 STRLEN len; 2185 STRLEN len;
2156 const char *str = SvPV (jsonstr, len); 2186 const char *str = SvPV (jsonstr, len);
2157 STRLEN cur = SvCUR (self->incr_text); 2187 STRLEN cur = SvCUR (self->incr_text);
2158 2188
2159 if (SvLEN (self->incr_text) <= cur + len) 2189 if (SvLEN (self->incr_text) - cur <= len)
2160 SvGROW (self->incr_text, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 2190 json_sv_grow (self->incr_text, cur, len);
2161 2191
2162 Move (str, SvEND (self->incr_text), len, char); 2192 Move (str, SvEND (self->incr_text), len, char);
2163 SvCUR_set (self->incr_text, SvCUR (self->incr_text) + len); 2193 SvCUR_set (self->incr_text, SvCUR (self->incr_text) + len);
2164 *SvEND (self->incr_text) = 0; // this should basically be a nop, too, but make sure it's there 2194 *SvEND (self->incr_text) = 0; // this should basically be a nop, too, but make sure it's there
2165 } 2195 }
2167 2197
2168 if (GIMME_V != G_VOID) 2198 if (GIMME_V != G_VOID)
2169 do 2199 do
2170 { 2200 {
2171 SV *sv; 2201 SV *sv;
2172 char *offset; 2202 STRLEN offset;
2173 2203
2174 if (!INCR_DONE (self)) 2204 if (!INCR_DONE (self))
2175 { 2205 {
2176 incr_parse (self); 2206 incr_parse (self);
2177 2207
2193 } 2223 }
2194 2224
2195 PUTBACK; sv = decode_json (self->incr_text, self, &offset); SPAGAIN; 2225 PUTBACK; sv = decode_json (self->incr_text, self, &offset); SPAGAIN;
2196 XPUSHs (sv); 2226 XPUSHs (sv);
2197 2227
2198 self->incr_pos -= offset - SvPVX (self->incr_text); 2228 self->incr_pos -= offset;
2199 self->incr_nest = 0; 2229 self->incr_nest = 0;
2200 self->incr_mode = 0; 2230 self->incr_mode = 0;
2201 2231
2202 sv_chop (self->incr_text, offset); 2232 sv_chop (self->incr_text, SvPVX (self->incr_text) + offset);
2203 } 2233 }
2204 while (GIMME_V == G_ARRAY); 2234 while (GIMME_V == G_ARRAY);
2205} 2235}
2206 2236
2207SV *incr_text (JSON *self) 2237SV *incr_text (JSON *self)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines