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

Side by Side Diff: Source/core/css/CSSTokenizer-in.cpp

Issue 230173005: Fix for ASSERT and more with bad CSS input. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@CHR-1552
Patch Set: ParseURI: Now with enum instead of bool. Created 6 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 | « LayoutTests/fast/css/css-escaped-identifier.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> 5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> 6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) 7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/)
8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. 8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
9 * Copyright (C) 2012 Intel Corporation. All rights reserved. 9 * Copyright (C) 2012 Intel Corporation. All rights reserved.
10 * 10 *
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 return tokenLocation<UChar>(); 346 return tokenLocation<UChar>();
347 } 347 }
348 348
349 template <typename CharacterType> 349 template <typename CharacterType>
350 inline bool CSSTokenizer::isIdentifierStart() 350 inline bool CSSTokenizer::isIdentifierStart()
351 { 351 {
352 // Check whether an identifier is started. 352 // Check whether an identifier is started.
353 return isIdentifierStartAfterDash((*currentCharacter<CharacterType>() != '-' ) ? currentCharacter<CharacterType>() : currentCharacter<CharacterType>() + 1); 353 return isIdentifierStartAfterDash((*currentCharacter<CharacterType>() != '-' ) ? currentCharacter<CharacterType>() : currentCharacter<CharacterType>() + 1);
354 } 354 }
355 355
356 enum CheckStringValidationMode {
357 AbortIfInvalid,
358 SkipInvalid
359 };
360
356 template <typename CharacterType> 361 template <typename CharacterType>
357 static inline CharacterType* checkAndSkipString(CharacterType* currentCharacter, int quote) 362 static inline CharacterType* checkAndSkipString(CharacterType* currentCharacter, int quote, CheckStringValidationMode mode)
358 { 363 {
359 // Returns with 0, if string check is failed. Otherwise 364 // If mode is AbortIfInvalid and the string check fails it returns
360 // it returns with the following character. This is necessary 365 // with 0. Otherwise it returns with a pointer to the first
361 // since we cannot revert escape sequences, thus strings 366 // character after the string.
362 // must be validated before parsing.
363 while (true) { 367 while (true) {
364 if (UNLIKELY(*currentCharacter == quote)) { 368 if (UNLIKELY(*currentCharacter == quote)) {
365 // String parsing is successful. 369 // String parsing is successful.
366 return currentCharacter + 1; 370 return currentCharacter + 1;
367 } 371 }
368 if (UNLIKELY(!*currentCharacter)) { 372 if (UNLIKELY(!*currentCharacter)) {
369 // String parsing is successful up to end of input. 373 // String parsing is successful up to end of input.
370 return currentCharacter; 374 return currentCharacter;
371 } 375 }
372 if (UNLIKELY(*currentCharacter <= '\r' && (*currentCharacter == '\n' || (*currentCharacter | 0x1) == '\r'))) { 376 if (mode == AbortIfInvalid && UNLIKELY(*currentCharacter <= '\r' && (*cu rrentCharacter == '\n' || (*currentCharacter | 0x1) == '\r'))) {
373 // String parsing is failed for character '\n', '\f' or '\r'. 377 // String parsing is failed for character '\n', '\f' or '\r'.
374 return 0; 378 return 0;
375 } 379 }
376 380
377 if (LIKELY(currentCharacter[0] != '\\')) { 381 if (LIKELY(currentCharacter[0] != '\\')) {
378 ++currentCharacter; 382 ++currentCharacter;
379 } else if (currentCharacter[1] == '\n' || currentCharacter[1] == '\f') { 383 } else if (currentCharacter[1] == '\n' || currentCharacter[1] == '\f') {
380 currentCharacter += 2; 384 currentCharacter += 2;
381 } else if (currentCharacter[1] == '\r') { 385 } else if (currentCharacter[1] == '\r') {
382 currentCharacter += currentCharacter[2] == '\n' ? 3 : 2; 386 currentCharacter += currentCharacter[2] == '\n' ? 3 : 2;
383 } else { 387 } else {
384 currentCharacter = checkAndSkipEscape(currentCharacter); 388 CharacterType* next = checkAndSkipEscape(currentCharacter);
385 if (!currentCharacter) 389 if (!next) {
386 return 0; 390 if (mode == AbortIfInvalid)
391 return 0;
392 next = currentCharacter + 1;
393 }
394 currentCharacter = next;
387 } 395 }
388 } 396 }
389 } 397 }
390 398
391 template <typename CharacterType> 399 template <typename CharacterType>
392 unsigned CSSTokenizer::parseEscape(CharacterType*& src) 400 unsigned CSSTokenizer::parseEscape(CharacterType*& src)
393 { 401 {
394 ASSERT(*src == '\\' && isCSSEscape(src[1])); 402 ASSERT(*src == '\\' && isCSSEscape(src[1]));
395 403
396 unsigned unicode = 0; 404 unsigned unicode = 0;
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 } 519 }
512 520
513 template <typename SrcCharacterType> 521 template <typename SrcCharacterType>
514 size_t CSSTokenizer::peekMaxStringLen(SrcCharacterType* src, UChar quote) 522 size_t CSSTokenizer::peekMaxStringLen(SrcCharacterType* src, UChar quote)
515 { 523 {
516 // The decoded form of a CSS string (after resolving escape 524 // The decoded form of a CSS string (after resolving escape
517 // sequences) will not contain more characters (ASCII or UTF-16 525 // sequences) will not contain more characters (ASCII or UTF-16
518 // codepoints) than the input. This code can therefore ignore 526 // codepoints) than the input. This code can therefore ignore
519 // escape sequences completely and just return the length of the 527 // escape sequences completely and just return the length of the
520 // input string (possibly including terminating quote if any). 528 // input string (possibly including terminating quote if any).
521 SrcCharacterType* end = checkAndSkipString(src, quote); 529 SrcCharacterType* end = checkAndSkipString(src, quote, SkipInvalid);
522 return end ? end - src : 0; 530 return end ? end - src : 0;
523 } 531 }
524 532
525 template <typename SrcCharacterType, typename DestCharacterType> 533 template <typename SrcCharacterType, typename DestCharacterType>
526 inline bool CSSTokenizer::parseStringInternal(SrcCharacterType*& src, DestCharac terType*& result, UChar quote) 534 inline bool CSSTokenizer::parseStringInternal(SrcCharacterType*& src, DestCharac terType*& result, UChar quote)
527 { 535 {
528 while (true) { 536 while (true) {
529 if (UNLIKELY(*src == quote)) { 537 if (UNLIKELY(*src == quote)) {
530 // String parsing is done. 538 // String parsing is done.
531 ++src; 539 ++src;
532 return true; 540 return true;
533 } 541 }
534 if (UNLIKELY(!*src)) { 542 if (UNLIKELY(!*src)) {
535 // String parsing is done, but don't advance pointer if at the end o f input. 543 // String parsing is done, but don't advance pointer if at the end o f input.
536 return true; 544 return true;
537 } 545 }
538 ASSERT(*src > '\r' || (*src < '\n' && *src) || *src == '\v');
539
540 if (LIKELY(src[0] != '\\')) { 546 if (LIKELY(src[0] != '\\')) {
541 *result++ = *src++; 547 *result++ = *src++;
542 } else if (src[1] == '\n' || src[1] == '\f') { 548 } else if (src[1] == '\n' || src[1] == '\f') {
543 src += 2; 549 src += 2;
544 } else if (src[1] == '\r') { 550 } else if (src[1] == '\r') {
545 src += src[2] == '\n' ? 3 : 2; 551 src += src[2] == '\n' ? 3 : 2;
546 } else { 552 } else {
547 SrcCharacterType* savedEscapeStart = src; 553 SrcCharacterType* savedEscapeStart = src;
548 unsigned unicode = parseEscape<SrcCharacterType>(src); 554 unsigned unicode = parseEscape<SrcCharacterType>(src);
549 if (unicode > 0xff && sizeof(DestCharacterType) == 1) { 555 if (unicode > 0xff && sizeof(DestCharacterType) == 1) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 resultString.init(start, result - start); 588 resultString.init(start, result - start);
583 } 589 }
584 590
585 template <typename CharacterType> 591 template <typename CharacterType>
586 inline bool CSSTokenizer::findURI(CharacterType*& start, CharacterType*& end, UC har& quote) 592 inline bool CSSTokenizer::findURI(CharacterType*& start, CharacterType*& end, UC har& quote)
587 { 593 {
588 start = skipWhiteSpace(currentCharacter<CharacterType>()); 594 start = skipWhiteSpace(currentCharacter<CharacterType>());
589 595
590 if (*start == '"' || *start == '\'') { 596 if (*start == '"' || *start == '\'') {
591 quote = *start++; 597 quote = *start++;
592 end = checkAndSkipString(start, quote); 598 end = checkAndSkipString(start, quote, AbortIfInvalid);
593 if (!end) 599 if (!end)
594 return false; 600 return false;
595 } else { 601 } else {
596 quote = 0; 602 quote = 0;
597 end = start; 603 end = start;
598 while (isURILetter(*end)) { 604 while (isURILetter(*end)) {
599 if (LIKELY(*end != '\\')) { 605 if (LIKELY(*end != '\\')) {
600 ++end; 606 ++end;
601 } else { 607 } else {
602 end = checkAndSkipEscape(end); 608 end = checkAndSkipEscape(end);
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after
1361 if (m_parsingMode == MediaQueryMode || m_parsingMode == SupportsMode) 1367 if (m_parsingMode == MediaQueryMode || m_parsingMode == SupportsMode)
1362 m_parsingMode = NormalMode; 1368 m_parsingMode = NormalMode;
1363 break; 1369 break;
1364 1370
1365 case CharacterEndNthChild: 1371 case CharacterEndNthChild:
1366 if (m_parsingMode == NthChildMode) 1372 if (m_parsingMode == NthChildMode)
1367 m_parsingMode = NormalMode; 1373 m_parsingMode = NormalMode;
1368 break; 1374 break;
1369 1375
1370 case CharacterQuote: 1376 case CharacterQuote:
1371 if (checkAndSkipString(currentCharacter<SrcCharacterType>(), m_token)) { 1377 if (checkAndSkipString(currentCharacter<SrcCharacterType>(), m_token, Ab ortIfInvalid)) {
1372 ++result; 1378 ++result;
1373 parseString<SrcCharacterType>(result, yylval->string, m_token); 1379 parseString<SrcCharacterType>(result, yylval->string, m_token);
1374 m_token = STRING; 1380 m_token = STRING;
1375 } 1381 }
1376 break; 1382 break;
1377 1383
1378 case CharacterExclamationMark: { 1384 case CharacterExclamationMark: {
1379 SrcCharacterType* start = skipWhiteSpace(currentCharacter<SrcCharacterTy pe>()); 1385 SrcCharacterType* start = skipWhiteSpace(currentCharacter<SrcCharacterTy pe>());
1380 if (isEqualToCSSIdentifier(start, "important")) { 1386 if (isEqualToCSSIdentifier(start, "important")) {
1381 m_token = IMPORTANT_SYM; 1387 m_token = IMPORTANT_SYM;
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
1580 m_dataStart16[length - 1] = 0; 1586 m_dataStart16[length - 1] = 0;
1581 1587
1582 m_is8BitSource = false; 1588 m_is8BitSource = false;
1583 m_currentCharacter8 = 0; 1589 m_currentCharacter8 = 0;
1584 m_currentCharacter16 = m_dataStart16.get(); 1590 m_currentCharacter16 = m_dataStart16.get();
1585 setTokenStart<UChar>(m_currentCharacter16); 1591 setTokenStart<UChar>(m_currentCharacter16);
1586 m_lexFunc = &CSSTokenizer::realLex<UChar>; 1592 m_lexFunc = &CSSTokenizer::realLex<UChar>;
1587 } 1593 }
1588 1594
1589 } // namespace WebCore 1595 } // namespace WebCore
OLDNEW
« no previous file with comments | « LayoutTests/fast/css/css-escaped-identifier.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698