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.129 by root, Wed Nov 16 18:06:34 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
361} enc_t; 387} enc_t;
362 388
363INLINE void 389INLINE void
364need (enc_t *enc, STRLEN len) 390need (enc_t *enc, STRLEN len)
365{ 391{
366 if (expect_false (enc->cur + len >= enc->end)) 392 if (expect_false ((uintptr_t)(enc->end - enc->cur) < len))
367 { 393 {
368 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv); 394 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv);
369 SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 395 char *buf = json_sv_grow (enc->sv, cur, len);
370 enc->cur = SvPVX (enc->sv) + cur; 396 enc->cur = buf + cur;
371 enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1; 397 enc->end = buf + SvLEN (enc->sv) - 1;
372 } 398 }
373} 399}
374 400
375INLINE void 401INLINE void
376encode_ch (enc_t *enc, char ch) 402encode_ch (enc_t *enc, char ch)
392 418
393 if (expect_true (ch >= 0x20 && ch < 0x80)) // most common case 419 if (expect_true (ch >= 0x20 && ch < 0x80)) // most common case
394 { 420 {
395 if (expect_false (ch == '"')) // but with slow exceptions 421 if (expect_false (ch == '"')) // but with slow exceptions
396 { 422 {
397 need (enc, len += 1); 423 need (enc, len + 1);
398 *enc->cur++ = '\\'; 424 *enc->cur++ = '\\';
399 *enc->cur++ = '"'; 425 *enc->cur++ = '"';
400 } 426 }
401 else if (expect_false (ch == '\\')) 427 else if (expect_false (ch == '\\'))
402 { 428 {
403 need (enc, len += 1); 429 need (enc, len + 1);
404 *enc->cur++ = '\\'; 430 *enc->cur++ = '\\';
405 *enc->cur++ = '\\'; 431 *enc->cur++ = '\\';
406 } 432 }
407 else 433 else
408 *enc->cur++ = ch; 434 *enc->cur++ = ch;
411 } 437 }
412 else 438 else
413 { 439 {
414 switch (ch) 440 switch (ch)
415 { 441 {
416 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;
417 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;
418 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;
419 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;
420 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;
421 447
422 default: 448 default:
423 { 449 {
424 STRLEN clen; 450 STRLEN clen;
425 UV uch; 451 UV uch;
441 if (uch >= 0x10000UL) 467 if (uch >= 0x10000UL)
442 { 468 {
443 if (uch >= 0x110000UL) 469 if (uch >= 0x110000UL)
444 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);
445 471
446 need (enc, len += 11); 472 need (enc, len + 11);
447 sprintf (enc->cur, "\\u%04x\\u%04x", 473 sprintf (enc->cur, "\\u%04x\\u%04x",
448 (int)((uch - 0x10000) / 0x400 + 0xD800), 474 (int)((uch - 0x10000) / 0x400 + 0xD800),
449 (int)((uch - 0x10000) % 0x400 + 0xDC00)); 475 (int)((uch - 0x10000) % 0x400 + 0xDC00));
450 enc->cur += 12; 476 enc->cur += 12;
451 } 477 }
452 else 478 else
453 { 479 {
454 need (enc, len += 5); 480 need (enc, len + 5);
455 *enc->cur++ = '\\'; 481 *enc->cur++ = '\\';
456 *enc->cur++ = 'u'; 482 *enc->cur++ = 'u';
457 *enc->cur++ = PL_hexdigit [ uch >> 12 ]; 483 *enc->cur++ = PL_hexdigit [ uch >> 12 ];
458 *enc->cur++ = PL_hexdigit [(uch >> 8) & 15]; 484 *enc->cur++ = PL_hexdigit [(uch >> 8) & 15];
459 *enc->cur++ = PL_hexdigit [(uch >> 4) & 15]; 485 *enc->cur++ = PL_hexdigit [(uch >> 4) & 15];
467 *enc->cur++ = uch; 493 *enc->cur++ = uch;
468 str += clen; 494 str += clen;
469 } 495 }
470 else if (is_utf8) 496 else if (is_utf8)
471 { 497 {
472 need (enc, len += clen); 498 need (enc, len + clen);
473 do 499 do
474 { 500 {
475 *enc->cur++ = *str++; 501 *enc->cur++ = *str++;
476 } 502 }
477 while (--clen); 503 while (--clen);
478 } 504 }
479 else 505 else
480 { 506 {
481 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
482 enc->cur = encode_utf8 (enc->cur, uch); 508 enc->cur = encode_utf8 (enc->cur, uch);
483 ++str; 509 ++str;
484 } 510 }
485 } 511 }
486 } 512 }
1167 1193
1168 if (sv) 1194 if (sv)
1169 { 1195 {
1170 STRLEN cur = SvCUR (sv); 1196 STRLEN cur = SvCUR (sv);
1171 1197
1172 if (SvLEN (sv) <= cur + len) 1198 if (SvLEN (sv) - cur <= len)
1173 SvGROW (sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 1199 json_sv_grow (sv, cur, len);
1174 1200
1175 memcpy (SvPVX (sv) + SvCUR (sv), buf, len); 1201 memcpy (SvPVX (sv) + SvCUR (sv), buf, len);
1176 SvCUR_set (sv, SvCUR (sv) + len); 1202 SvCUR_set (sv, SvCUR (sv) + len);
1177 } 1203 }
1178 else 1204 else
2158 { 2184 {
2159 STRLEN len; 2185 STRLEN len;
2160 const char *str = SvPV (jsonstr, len); 2186 const char *str = SvPV (jsonstr, len);
2161 STRLEN cur = SvCUR (self->incr_text); 2187 STRLEN cur = SvCUR (self->incr_text);
2162 2188
2163 if (SvLEN (self->incr_text) <= cur + len) 2189 if (SvLEN (self->incr_text) - cur <= len)
2164 SvGROW (self->incr_text, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 2190 json_sv_grow (self->incr_text, cur, len);
2165 2191
2166 Move (str, SvEND (self->incr_text), len, char); 2192 Move (str, SvEND (self->incr_text), len, char);
2167 SvCUR_set (self->incr_text, SvCUR (self->incr_text) + len); 2193 SvCUR_set (self->incr_text, SvCUR (self->incr_text) + len);
2168 *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
2169 } 2195 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines