Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Side by Side Diff: src/json-parser.h

Issue 1041483004: Fix JSON parser Handle leak (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix int width issue Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/heap.cc ('k') | test/mjsunit/regress/regress-3976.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_JSON_PARSER_H_ 5 #ifndef V8_JSON_PARSER_H_
6 #define V8_JSON_PARSER_H_ 6 #define V8_JSON_PARSER_H_
7 7
8 #include "src/v8.h" 8 #include "src/v8.h"
9 9
10 #include "src/char-predicates-inl.h" 10 #include "src/char-predicates-inl.h"
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 Handle<Object> ParseJsonValue(); 148 Handle<Object> ParseJsonValue();
149 149
150 // Parse a JSON object literal (grammar production JSONObject). 150 // Parse a JSON object literal (grammar production JSONObject).
151 // An object literal is a squiggly-braced and comma separated sequence 151 // An object literal is a squiggly-braced and comma separated sequence
152 // (possibly empty) of key/value pairs, where the key is a JSON string 152 // (possibly empty) of key/value pairs, where the key is a JSON string
153 // literal, the value is a JSON value, and the two are separated by a colon. 153 // literal, the value is a JSON value, and the two are separated by a colon.
154 // A JSON array doesn't allow numbers and identifiers as keys, like a 154 // A JSON array doesn't allow numbers and identifiers as keys, like a
155 // JavaScript array. 155 // JavaScript array.
156 Handle<Object> ParseJsonObject(); 156 Handle<Object> ParseJsonObject();
157 157
158 // Helper for ParseJsonObject. Parses the form "123": obj, which is recorded
159 // as an element, not a property.
160 bool ParseElement(Handle<JSObject> json_object);
161
158 // Parses a JSON array literal (grammar production JSONArray). An array 162 // Parses a JSON array literal (grammar production JSONArray). An array
159 // literal is a square-bracketed and comma separated sequence (possibly empty) 163 // literal is a square-bracketed and comma separated sequence (possibly empty)
160 // of JSON values. 164 // of JSON values.
161 // A JSON array doesn't allow leaving out values from the sequence, nor does 165 // A JSON array doesn't allow leaving out values from the sequence, nor does
162 // it allow a terminal comma, like a JavaScript array does. 166 // it allow a terminal comma, like a JavaScript array does.
163 Handle<Object> ParseJsonArray(); 167 Handle<Object> ParseJsonArray();
164 168
165 169
166 // Mark that a parsing error has happened at the current token, and 170 // Mark that a parsing error has happened at the current token, and
167 // return a null handle. Primarily for readability. 171 // return a null handle. Primarily for readability.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 AdvanceGetChar() == 'l') { 296 AdvanceGetChar() == 'l') {
293 AdvanceSkipWhitespace(); 297 AdvanceSkipWhitespace();
294 return factory()->null_value(); 298 return factory()->null_value();
295 } 299 }
296 return ReportUnexpectedCharacter(); 300 return ReportUnexpectedCharacter();
297 } 301 }
298 return ReportUnexpectedCharacter(); 302 return ReportUnexpectedCharacter();
299 } 303 }
300 304
301 305
306 template <bool seq_one_byte>
307 bool JsonParser<seq_one_byte>::ParseElement(Handle<JSObject> json_object) {
308 uint32_t index = 0;
309 // Maybe an array index, try to parse it.
310 if (c0_ == '0') {
311 // With a leading zero, the string has to be "0" only to be an index.
312 Advance();
313 } else {
314 do {
315 int d = c0_ - '0';
316 if (index > 429496729U - ((d > 5) ? 1 : 0)) break;
317 index = (index * 10) + d;
318 Advance();
319 } while (IsDecimalDigit(c0_));
320 }
321
322 if (c0_ == '"') {
323 // Successfully parsed index, parse and store element.
324 AdvanceSkipWhitespace();
325
326 if (c0_ == ':') {
327 AdvanceSkipWhitespace();
328 Handle<Object> value = ParseJsonValue();
329 if (!value.is_null()) {
330 JSObject::SetOwnElement(json_object, index, value, SLOPPY).Assert();
331 return true;
332 }
333 }
334 }
335 return false;
336 }
337
302 // Parse a JSON object. Position must be right at '{'. 338 // Parse a JSON object. Position must be right at '{'.
303 template <bool seq_one_byte> 339 template <bool seq_one_byte>
304 Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() { 340 Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
305 HandleScope scope(isolate()); 341 HandleScope scope(isolate());
306 Handle<JSObject> json_object = 342 Handle<JSObject> json_object =
307 factory()->NewJSObject(object_constructor(), pretenure_); 343 factory()->NewJSObject(object_constructor(), pretenure_);
308 Handle<Map> map(json_object->map()); 344 Handle<Map> map(json_object->map());
309 int descriptor = 0; 345 int descriptor = 0;
310 ZoneList<Handle<Object> > properties(8, zone()); 346 ZoneList<Handle<Object> > properties(8, zone());
311 DCHECK_EQ(c0_, '{'); 347 DCHECK_EQ(c0_, '{');
312 348
313 bool transitioning = true; 349 bool transitioning = true;
314 350
315 AdvanceSkipWhitespace(); 351 AdvanceSkipWhitespace();
316 if (c0_ != '}') { 352 if (c0_ != '}') {
317 do { 353 do {
318 if (c0_ != '"') return ReportUnexpectedCharacter(); 354 if (c0_ != '"') return ReportUnexpectedCharacter();
319 355
320 int start_position = position_; 356 int start_position = position_;
321 Advance(); 357 Advance();
322 358
323 uint32_t index = 0;
324 if (IsDecimalDigit(c0_)) { 359 if (IsDecimalDigit(c0_)) {
325 // Maybe an array index, try to parse it. 360 if (ParseElement(json_object)) continue;
326 if (c0_ == '0') {
327 // With a leading zero, the string has to be "0" only to be an index.
328 Advance();
329 } else {
330 do {
331 int d = c0_ - '0';
332 if (index > 429496729U - ((d > 5) ? 1 : 0)) break;
333 index = (index * 10) + d;
334 Advance();
335 } while (IsDecimalDigit(c0_));
336 }
337
338 if (c0_ == '"') {
339 // Successfully parsed index, parse and store element.
340 AdvanceSkipWhitespace();
341
342 if (c0_ != ':') return ReportUnexpectedCharacter();
343 AdvanceSkipWhitespace();
344 Handle<Object> value = ParseJsonValue();
345 if (value.is_null()) return ReportUnexpectedCharacter();
346
347 JSObject::SetOwnElement(json_object, index, value, SLOPPY).Assert();
348 continue;
349 }
350 // Not an index, fallback to the slow path.
351 } 361 }
362 // Not an index, fallback to the slow path.
352 363
353 position_ = start_position; 364 position_ = start_position;
354 #ifdef DEBUG 365 #ifdef DEBUG
355 c0_ = '"'; 366 c0_ = '"';
356 #endif 367 #endif
357 368
358 Handle<String> key; 369 Handle<String> key;
359 Handle<Object> value; 370 Handle<Object> value;
360 371
361 // Try to follow existing transitions as long as possible. Once we stop 372 // Try to follow existing transitions as long as possible. Once we stop
362 // transitioning, no transition can be found anymore. 373 // transitioning, no transition can be found anymore.
374 DCHECK(transitioning);
375 // First check whether there is a single expected transition. If so, try
376 // to parse it first.
377 bool follow_expected = false;
378 Handle<Map> target;
379 if (seq_one_byte) {
380 key = TransitionArray::ExpectedTransitionKey(map);
381 follow_expected = !key.is_null() && ParseJsonString(key);
382 }
383 // If the expected transition hits, follow it.
384 if (follow_expected) {
385 target = TransitionArray::ExpectedTransitionTarget(map);
386 } else {
387 // If the expected transition failed, parse an internalized string and
388 // try to find a matching transition.
389 key = ParseJsonInternalizedString();
390 if (key.is_null()) return ReportUnexpectedCharacter();
391
392 target = TransitionArray::FindTransitionToField(map, key);
393 // If a transition was found, follow it and continue.
394 transitioning = !target.is_null();
395 }
396 if (c0_ != ':') return ReportUnexpectedCharacter();
397
398 AdvanceSkipWhitespace();
399 value = ParseJsonValue();
400 if (value.is_null()) return ReportUnexpectedCharacter();
401
363 if (transitioning) { 402 if (transitioning) {
364 // First check whether there is a single expected transition. If so, try 403 PropertyDetails details =
365 // to parse it first. 404 target->instance_descriptors()->GetDetails(descriptor);
366 bool follow_expected = false; 405 Representation expected_representation = details.representation();
367 Handle<Map> target; 406
368 if (seq_one_byte) { 407 if (value->FitsRepresentation(expected_representation)) {
369 key = TransitionArray::ExpectedTransitionKey(map); 408 if (expected_representation.IsHeapObject() &&
370 follow_expected = !key.is_null() && ParseJsonString(key); 409 !target->instance_descriptors()
410 ->GetFieldType(descriptor)
411 ->NowContains(value)) {
412 Handle<HeapType> value_type(
413 value->OptimalType(isolate(), expected_representation));
414 Map::GeneralizeFieldType(target, descriptor,
415 expected_representation, value_type);
416 }
417 DCHECK(target->instance_descriptors()
418 ->GetFieldType(descriptor)
419 ->NowContains(value));
420 properties.Add(value, zone());
421 map = target;
422 descriptor++;
423 continue;
424 } else {
425 transitioning = false;
371 } 426 }
372 // If the expected transition hits, follow it. 427 }
373 if (follow_expected) {
374 target = TransitionArray::ExpectedTransitionTarget(map);
375 } else {
376 // If the expected transition failed, parse an internalized string and
377 // try to find a matching transition.
378 key = ParseJsonInternalizedString();
379 if (key.is_null()) return ReportUnexpectedCharacter();
380 428
381 target = TransitionArray::FindTransitionToField(map, key); 429 DCHECK(!transitioning);
382 // If a transition was found, follow it and continue. 430
383 transitioning = !target.is_null(); 431 // Commit the intermediate state to the object and stop transitioning.
432 CommitStateToJsonObject(json_object, map, &properties);
433
434 Runtime::DefineObjectProperty(json_object, key, value, NONE).Check();
435 } while (transitioning && MatchSkipWhiteSpace(','));
436
437 // If we transitioned until the very end, transition the map now.
438 if (transitioning) {
439 CommitStateToJsonObject(json_object, map, &properties);
440 } else {
441 while (MatchSkipWhiteSpace(',')) {
442 HandleScope local_scope(isolate());
443 if (c0_ != '"') return ReportUnexpectedCharacter();
444
445 int start_position = position_;
446 Advance();
447
448 if (IsDecimalDigit(c0_)) {
449 if (ParseElement(json_object)) continue;
384 } 450 }
385 if (c0_ != ':') return ReportUnexpectedCharacter(); 451 // Not an index, fallback to the slow path.
386 452
387 AdvanceSkipWhitespace(); 453 position_ = start_position;
388 value = ParseJsonValue(); 454 #ifdef DEBUG
389 if (value.is_null()) return ReportUnexpectedCharacter(); 455 c0_ = '"';
456 #endif
390 457
391 if (transitioning) { 458 Handle<String> key;
392 PropertyDetails details = 459 Handle<Object> value;
393 target->instance_descriptors()->GetDetails(descriptor);
394 Representation expected_representation = details.representation();
395 460
396 if (value->FitsRepresentation(expected_representation)) {
397 if (expected_representation.IsHeapObject() &&
398 !target->instance_descriptors()
399 ->GetFieldType(descriptor)
400 ->NowContains(value)) {
401 Handle<HeapType> value_type(value->OptimalType(
402 isolate(), expected_representation));
403 Map::GeneralizeFieldType(target, descriptor,
404 expected_representation, value_type);
405 }
406 DCHECK(target->instance_descriptors()->GetFieldType(
407 descriptor)->NowContains(value));
408 properties.Add(value, zone());
409 map = target;
410 descriptor++;
411 continue;
412 } else {
413 transitioning = false;
414 }
415 }
416
417 // Commit the intermediate state to the object and stop transitioning.
418 CommitStateToJsonObject(json_object, map, &properties);
419 } else {
420 key = ParseJsonInternalizedString(); 461 key = ParseJsonInternalizedString();
421 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); 462 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
422 463
423 AdvanceSkipWhitespace(); 464 AdvanceSkipWhitespace();
424 value = ParseJsonValue(); 465 value = ParseJsonValue();
425 if (value.is_null()) return ReportUnexpectedCharacter(); 466 if (value.is_null()) return ReportUnexpectedCharacter();
467
468 Runtime::DefineObjectProperty(json_object, key, value, NONE).Check();
426 } 469 }
470 }
427 471
428 Runtime::DefineObjectProperty(json_object, key, value, NONE).Check();
429 } while (MatchSkipWhiteSpace(','));
430 if (c0_ != '}') { 472 if (c0_ != '}') {
431 return ReportUnexpectedCharacter(); 473 return ReportUnexpectedCharacter();
432 } 474 }
433
434 // If we transitioned until the very end, transition the map now.
435 if (transitioning) {
436 CommitStateToJsonObject(json_object, map, &properties);
437 }
438 } 475 }
439 AdvanceSkipWhitespace(); 476 AdvanceSkipWhitespace();
440 return scope.CloseAndEscape(json_object); 477 return scope.CloseAndEscape(json_object);
441 } 478 }
442 479
443 480
444 template <bool seq_one_byte> 481 template <bool seq_one_byte>
445 void JsonParser<seq_one_byte>::CommitStateToJsonObject( 482 void JsonParser<seq_one_byte>::CommitStateToJsonObject(
446 Handle<JSObject> json_object, Handle<Map> map, 483 Handle<JSObject> json_object, Handle<Map> map,
447 ZoneList<Handle<Object> >* properties) { 484 ZoneList<Handle<Object> >* properties) {
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 830
794 DCHECK_EQ('"', c0_); 831 DCHECK_EQ('"', c0_);
795 // Advance past the last '"'. 832 // Advance past the last '"'.
796 AdvanceSkipWhitespace(); 833 AdvanceSkipWhitespace();
797 return result; 834 return result;
798 } 835 }
799 836
800 } } // namespace v8::internal 837 } } // namespace v8::internal
801 838
802 #endif // V8_JSON_PARSER_H_ 839 #endif // V8_JSON_PARSER_H_
OLDNEW
« no previous file with comments | « src/heap/heap.cc ('k') | test/mjsunit/regress/regress-3976.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698