Changeset 244828 in webkit
- Timestamp:
- May 1, 2019, 10:33:03 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 30 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/css3/escape-dom-api-expected.txt (modified) (2 diffs)
-
LayoutTests/fast/text/dangling-surrogates-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/ChangeLog (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/encoding/textdecoder-utf16-surrogates-expected.txt (modified) (1 diff)
-
LayoutTests/js/dom/webidl-type-mapping-expected.txt (modified) (2 diffs)
-
LayoutTests/js/invalid-utf8-in-syntax-error-expected.txt (modified) (1 diff)
-
LayoutTests/js/invalid-utf8-in-syntax-error.html (added)
-
Source/JavaScriptCore/API/JSClassRef.cpp (modified) (1 diff)
-
Source/JavaScriptCore/API/JSStringRef.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/wasm/WasmParser.h (modified) (1 diff)
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/wtf/text/AtomicString.cpp (modified) (1 diff)
-
Source/WTF/wtf/text/AtomicStringImpl.cpp (modified) (1 diff)
-
Source/WTF/wtf/text/AtomicStringImpl.h (modified) (1 diff)
-
Source/WTF/wtf/text/StringImpl.cpp (modified) (5 diffs)
-
Source/WTF/wtf/text/StringView.cpp (modified) (1 diff)
-
Source/WTF/wtf/text/WTFString.cpp (modified) (1 diff)
-
Source/WTF/wtf/unicode/UTF8Conversion.cpp (modified) (3 diffs)
-
Source/WTF/wtf/unicode/UTF8Conversion.h (modified) (2 diffs)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/ChangeLog-2010-12-06 (modified) (1 diff)
-
Source/WebCore/ChangeLog-2013-04-24 (modified) (1 diff)
-
Source/WebCore/platform/SharedBuffer.cpp (modified) (1 diff)
-
Source/WebCore/xml/XSLTProcessorLibxslt.cpp (modified) (2 diffs)
-
Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp (modified) (1 diff)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/Shared/API/APIString.h (modified) (2 diffs)
-
Source/WebKit/Shared/API/c/WKString.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r244827 r244828 1 2019-05-01 Darin Adler <darin@apple.com> 2 3 WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support 4 https://bugs.webkit.org/show_bug.cgi?id=195535 5 6 Reviewed by Alexey Proskuryakov. 7 8 * css3/escape-dom-api-expected.txt: 9 * fast/text/dangling-surrogates-expected.txt: 10 * js/dom/webidl-type-mapping-expected.txt: 11 * js/invalid-utf8-in-syntax-error-expected.txt: 12 Updated expected results to have the Unicode replacement character in cases where the 13 text contains unpaired surrogates. The tests are still doing the same operations, and 14 still getting the same results, but the text output no longer includes illegal UTF-8. 15 16 * js/invalid-utf8-in-syntax-error.html: Added. Before adding this, the test was 17 run, but unlike the rest of the tests in this directory, was only run as part of 18 run-javascriptcore-tests. There are two reasons for adding this. One is to be 19 consistent with the rest of the tests here and run a second time as part of the 20 broader WebKit tests. The second is that we can now use "--reset-results" to generate 21 new expected results, something that run-webkit-tests has but run-javascriptcore-tests 22 does not have. 23 1 24 2019-05-01 Shawn Roberts <sroberts@apple.com> 2 25 -
trunk/LayoutTests/css3/escape-dom-api-expected.txt
r244827 r244828 5 5 6 6 PASS CSS.escape.length is 1 7 PASS CSS.escape('\0') is " �"8 PASS CSS.escape('a\0') is "a �"9 PASS CSS.escape('\0b') is " �b"10 PASS CSS.escape('a\0b') is "a �b"11 PASS CSS.escape(' �') is "�"12 PASS CSS.escape('a �') is "a�"13 PASS CSS.escape(' �b') is "�b"14 PASS CSS.escape('a �b') is "a�b"7 PASS CSS.escape('\0') is "�" 8 PASS CSS.escape('a\0') is "a�" 9 PASS CSS.escape('\0b') is "�b" 10 PASS CSS.escape('a\0b') is "a�b" 11 PASS CSS.escape('�') is "�" 12 PASS CSS.escape('a�') is "a�" 13 PASS CSS.escape('�b') is "�b" 14 PASS CSS.escape('a�b') is "a�b" 15 15 PASS CSS.escape() threw exception TypeError: Not enough arguments. 16 16 PASS CSS.escape(undefined) is "undefined" … … 55 55 PASS CSS.escape('--') is "--" 56 56 PASS CSS.escape('--a') is "--a" 57 PASS CSS.escape(' Â-_©') is "Â-_©"58 PASS CSS.escape(' ÂÂÂÂÂÂ59 ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ') is "\\7f  60 ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ"61 PASS CSS.escape('  ¡¢') is " ¡¢"57 PASS CSS.escape('-_©') is "-_©" 58 PASS CSS.escape(' 59 ') is "\\7f 60 " 61 PASS CSS.escape(' ¡¢') is " ¡¢" 62 62 PASS CSS.escape('a0123456789b') is "a0123456789b" 63 63 PASS CSS.escape('abcdefghijklmnopqrstuvwxyz') is "abcdefghijklmnopqrstuvwxyz" 64 64 PASS CSS.escape('ABCDEFGHIJKLMNOPQRSTUVWXYZ') is "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 65 65 PASS CSS.escape(' !xy') is "\\ \\!xy" 66 PASS CSS.escape(' ð') is "ð"67 PASS CSS.escape(' í¼') is "\udf06"68 PASS CSS.escape(' í ´') is "\ud834"66 PASS CSS.escape('𝌆') is "𝌆" 67 PASS CSS.escape('�') is "\udf06" 68 PASS CSS.escape('�') is "\ud834" 69 69 PASS successfullyParsed is true 70 70 -
trunk/LayoutTests/fast/text/dangling-surrogates-expected.txt
r244827 r244828 4 4 5 5 6 PASS danglingFirst is " í "7 PASS danglingSecond is " í°"6 PASS danglingFirst is "�" 7 PASS danglingSecond is "�" 8 8 PASS successfullyParsed is true 9 9 -
trunk/LayoutTests/imported/w3c/ChangeLog
r244827 r244828 1 2019-05-01 Darin Adler <darin@apple.com> 2 3 WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support 4 https://bugs.webkit.org/show_bug.cgi?id=195535 5 6 Reviewed by Alexey Proskuryakov. 7 8 * web-platform-tests/encoding/textdecoder-utf16-surrogates-expected.txt: 9 Updated expected results to have the Unicode replacement character in cases where the 10 text contains unpaired surrogates. The tests are still doing the same operations, and 11 still getting the same results, but the text output no longer includes illegal UTF-8. 12 1 13 2019-05-01 Shawn Roberts <sroberts@apple.com> 2 14 -
trunk/LayoutTests/imported/w3c/web-platform-tests/encoding/textdecoder-utf16-surrogates-expected.txt
r244827 r244828 1 1 2 FAIL utf-16le - lone surrogate lead assert_equals: expected "\ufffd" but got " í "2 FAIL utf-16le - lone surrogate lead assert_equals: expected "\ufffd" but got "�" 3 3 FAIL utf-16le - lone surrogate lead (fatal flag set) assert_throws: function "function () { 4 4 new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input)) 5 5 }" did not throw 6 FAIL utf-16le - lone surrogate trail assert_equals: expected "\ufffd" but got " í°"6 FAIL utf-16le - lone surrogate trail assert_equals: expected "\ufffd" but got "�" 7 7 FAIL utf-16le - lone surrogate trail (fatal flag set) assert_throws: function "function () { 8 8 new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input)) 9 9 }" did not throw 10 FAIL utf-16le - unmatched surrogate lead assert_equals: expected "\ufffd\0" but got " í \0"10 FAIL utf-16le - unmatched surrogate lead assert_equals: expected "\ufffd\0" but got "�\0" 11 11 FAIL utf-16le - unmatched surrogate lead (fatal flag set) assert_throws: function "function () { 12 12 new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input)) 13 13 }" did not throw 14 FAIL utf-16le - unmatched surrogate trail assert_equals: expected "\ufffd\0" but got " í°\0"14 FAIL utf-16le - unmatched surrogate trail assert_equals: expected "\ufffd\0" but got "�\0" 15 15 FAIL utf-16le - unmatched surrogate trail (fatal flag set) assert_throws: function "function () { 16 16 new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input)) 17 17 }" did not throw 18 FAIL utf-16le - swapped surrogate pair assert_equals: expected "\ufffd\ufffd" but got " í°í "18 FAIL utf-16le - swapped surrogate pair assert_equals: expected "\ufffd\ufffd" but got "��" 19 19 FAIL utf-16le - swapped surrogate pair (fatal flag set) assert_throws: function "function () { 20 20 new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input)) -
trunk/LayoutTests/js/dom/webidl-type-mapping-expected.txt
r244827 r244828 1010 1010 converter.testUSVString = '!@#123ABCabc\x00\x80\xFF\r\n\t' 1011 1011 converter.testString = '!@#123ABCabc\x00\x80\xFF\r\n\t' 1012 PASS converter.testUSVString is "!@#123ABCabc\u0000 Âÿ\r\n\t"1013 PASS converter.testString is "!@#123ABCabc\u0000 Âÿ\r\n\t"1012 PASS converter.testUSVString is "!@#123ABCabc\u0000ÿ\r\n\t" 1013 PASS converter.testString is "!@#123ABCabc\u0000ÿ\r\n\t" 1014 1014 converter.testUSVString = '\u0100' 1015 1015 converter.testString = '\u0100' 1016 PASS converter.testUSVString is " Ä"1017 PASS converter.testString is " Ä"1016 PASS converter.testUSVString is "Ā" 1017 PASS converter.testString is "Ā" 1018 1018 PASS converter.testUSVString = {toString: function() { throw Error(); }} threw exception Error. 1019 1019 PASS converter.testString = {toString: function() { throw Error(); }} threw exception Error. 1020 PASS converter.testUSVString is " Ä"1021 PASS converter.testString is " Ä"1020 PASS converter.testUSVString is "Ā" 1021 PASS converter.testString is "Ā" 1022 1022 converter.testUSVString = "\ud800" 1023 1023 converter.testString = "\ud800" 1024 PASS converter.testUSVString is " �"1024 PASS converter.testUSVString is "�" 1025 1025 PASS converter.testString is "\ud800" 1026 1026 converter.testUSVString = "\udc00" 1027 1027 converter.testString = "\udc00" 1028 PASS converter.testUSVString is " �"1028 PASS converter.testUSVString is "�" 1029 1029 PASS converter.testString is "\udc00" 1030 1030 converter.testUSVString = "\ud800\u0000" 1031 1031 converter.testString = "\ud800\u0000" 1032 PASS converter.testUSVString is " �\u0000"1032 PASS converter.testUSVString is "�\u0000" 1033 1033 PASS converter.testString is "\ud800\u0000" 1034 1034 converter.testUSVString = "\udc00\u0000" 1035 1035 converter.testString = "\udc00\u0000" 1036 PASS converter.testUSVString is " �\u0000"1036 PASS converter.testUSVString is "�\u0000" 1037 1037 PASS converter.testString is "\udc00\u0000" 1038 1038 converter.testUSVString = "\udc00\ud800" 1039 1039 converter.testString = "\udc00\ud800" 1040 PASS converter.testUSVString is " ��"1040 PASS converter.testUSVString is "��" 1041 1041 PASS converter.testString is "\udc00\ud800" 1042 converter.testUSVString = " ð"1043 converter.testString = " ð"1044 PASS converter.testUSVString is " ð"1045 PASS converter.testString is " ð"1042 converter.testUSVString = "𝄞" 1043 converter.testString = "𝄞" 1044 PASS converter.testUSVString is "𝄞" 1045 PASS converter.testString is "𝄞" 1046 1046 converter.testByteString = '!@#123ABCabc\x00\x80\xFF\r\n\t' 1047 PASS converter.testByteString is "!@#123ABCabc\u0000 Âÿ\r\n\t"1047 PASS converter.testByteString is "!@#123ABCabc\u0000ÿ\r\n\t" 1048 1048 converter.testByteString = '\u00FF' 1049 PASS converter.testByteString is " ÿ"1049 PASS converter.testByteString is "ÿ" 1050 1050 PASS converter.testByteString = '\u0100' threw exception TypeError: Type error. 1051 PASS converter.testByteString is " ÿ"1051 PASS converter.testByteString is "ÿ" 1052 1052 PASS converter.testByteString = {toString: function() { throw Error(); }} threw exception Error. 1053 PASS converter.testByteString is " ÿ"1053 PASS converter.testByteString is "ÿ" 1054 1054 converter.testUSVString = true 1055 1055 converter.testString = true … … 1181 1181 PASS converter.testNodeRecord()['key2'] is document.documentElement 1182 1182 PASS converter.setTestNodeRecord({ key: 'hello' }) threw exception TypeError: Type error. 1183 converter.setTestLongRecord({' í ': 1 })1184 PASS converter.testLongRecord()[' í '] is 11185 converter.setTestNodeRecord({' í ': document })1186 PASS converter.testNodeRecord()[' �'] is document1187 converter.setTestLongRecord({' í°': 1 })1188 PASS converter.testLongRecord()[' í°'] is 11189 converter.setTestNodeRecord({' í°': document })1190 PASS converter.testNodeRecord()[' �'] is document1191 converter.setTestLongRecord({' í ': 1 })1192 PASS converter.testLongRecord()[' í \0'] is 11193 converter.setTestNodeRecord({' í ': document })1194 PASS converter.testNodeRecord()[' �\0'] is document1195 converter.setTestLongRecord({' í°': 1 })1196 PASS converter.testLongRecord()[' í°\0'] is 11197 converter.setTestNodeRecord({' í°': document })1198 PASS converter.testNodeRecord()[' �\0'] is document1199 converter.setTestLongRecord({' í°í ': 1 })1200 PASS converter.testLongRecord()[' í°í '] is 11201 converter.setTestNodeRecord({' í°í ': document })1202 PASS converter.testNodeRecord()[' ��'] is document1203 converter.setTestLongRecord({' ð': 1 })1204 PASS converter.testLongRecord()[' ð'] is 11205 converter.setTestNodeRecord({' ð': document })1206 PASS converter.testNodeRecord()[' ð'] is document1183 converter.setTestLongRecord({'�': 1 }) 1184 PASS converter.testLongRecord()['�'] is 1 1185 converter.setTestNodeRecord({'�': document }) 1186 PASS converter.testNodeRecord()['�'] is document 1187 converter.setTestLongRecord({'�': 1 }) 1188 PASS converter.testLongRecord()['�'] is 1 1189 converter.setTestNodeRecord({'�': document }) 1190 PASS converter.testNodeRecord()['�'] is document 1191 converter.setTestLongRecord({'�': 1 }) 1192 PASS converter.testLongRecord()['�\0'] is 1 1193 converter.setTestNodeRecord({'�': document }) 1194 PASS converter.testNodeRecord()['�\0'] is document 1195 converter.setTestLongRecord({'�': 1 }) 1196 PASS converter.testLongRecord()['�\0'] is 1 1197 converter.setTestNodeRecord({'�': document }) 1198 PASS converter.testNodeRecord()['�\0'] is document 1199 converter.setTestLongRecord({'��': 1 }) 1200 PASS converter.testLongRecord()['��'] is 1 1201 converter.setTestNodeRecord({'��': document }) 1202 PASS converter.testNodeRecord()['��'] is document 1203 converter.setTestLongRecord({'𝄞': 1 }) 1204 PASS converter.testLongRecord()['𝄞'] is 1 1205 converter.setTestNodeRecord({'𝄞': document }) 1206 PASS converter.testNodeRecord()['𝄞'] is document 1207 1207 converter.setTestSequenceRecord({ key: ['value', 'other value'] }) 1208 1208 PASS converter.testSequenceRecord().hasOwnProperty('key') is true 1209 1209 PASS 'key' in converter.testSequenceRecord() is true 1210 1210 PASS converter.testSequenceRecord()['key'] is ['value', 'other value'] 1211 PASS converter.setTestSequenceRecord({ ' Ä': ['value'] }) threw exception TypeError: Type error.1212 converter.setTestSequenceRecord({ ' ÿ': ['value'] })1213 PASS converter.testSequenceRecord()[' ÿ'] is ['value']1211 PASS converter.setTestSequenceRecord({ 'Ā': ['value'] }) threw exception TypeError: Type error. 1212 converter.setTestSequenceRecord({ 'ÿ': ['value'] }) 1213 PASS converter.testSequenceRecord()['ÿ'] is ['value'] 1214 1214 PASS converter.testImpureNaNUnrestrictedDouble is NaN 1215 1215 PASS converter.testImpureNaN2UnrestrictedDouble is NaN -
trunk/LayoutTests/js/invalid-utf8-in-syntax-error-expected.txt
r244827 r244828 4 4 5 5 6 PASS ({f(" íº")}) threw exception SyntaxError: Unexpected string literal "úÂ". Expected a parameter pattern or a ')' in parameter list..6 PASS ({f("�")}) threw exception SyntaxError: Unexpected string literal "�". Expected a parameter pattern or a ')' in parameter list.. 7 7 PASS successfullyParsed is true 8 8 -
trunk/Source/JavaScriptCore/API/JSClassRef.cpp
r244827 r244828 36 36 #include "JSCInlines.h" 37 37 #include <wtf/text/StringHash.h> 38 #include <wtf/unicode/UTF8Conversion.h>39 38 40 39 using namespace JSC; 41 using namespace WTF::Unicode;42 40 43 41 const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -
trunk/Source/JavaScriptCore/API/JSStringRef.cpp
r244827 r244828 50 50 bool sourceIsAllASCII; 51 51 const LChar* stringStart = reinterpret_cast<const LChar*>(string); 52 if (conver sionOK == convertUTF8ToUTF16(&string, string + length, &p, p + length, &sourceIsAllASCII)) {52 if (convertUTF8ToUTF16(string, string + length, &p, p + length, &sourceIsAllASCII)) { 53 53 if (sourceIsAllASCII) 54 54 return &OpaqueJSString::create(stringStart, length).leakRef(); … … 103 103 104 104 char* destination = buffer; 105 ConversionResult result;105 bool failed = false; 106 106 if (string->is8Bit()) { 107 107 const LChar* source = string->characters8(); 108 result =convertLatin1ToUTF8(&source, source + string->length(), &destination, destination + bufferSize - 1);108 convertLatin1ToUTF8(&source, source + string->length(), &destination, destination + bufferSize - 1); 109 109 } else { 110 110 const UChar* source = string->characters16(); 111 result = convertUTF16ToUTF8(&source, source + string->length(), &destination, destination + bufferSize - 1, true); 111 auto result = convertUTF16ToUTF8(&source, source + string->length(), &destination, destination + bufferSize - 1); 112 failed = result != ConversionOK && result != TargetExhausted; 112 113 } 113 114 114 115 *destination++ = '\0'; 115 if (result != conversionOK && result != targetExhausted) 116 return 0; 117 118 return destination - buffer; 116 return failed ? 0 : destination - buffer; 119 117 } 120 118 -
trunk/Source/JavaScriptCore/ChangeLog
r244827 r244828 1 2019-05-01 Darin Adler <darin@apple.com> 2 3 WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support 4 https://bugs.webkit.org/show_bug.cgi?id=195535 5 6 Reviewed by Alexey Proskuryakov. 7 8 * API/JSClassRef.cpp: Removed uneeded include of UTF8Conversion.h. 9 10 * API/JSStringRef.cpp: 11 (JSStringCreateWithUTF8CString): Updated for changes to convertUTF8ToUTF16. 12 (JSStringGetUTF8CString): Updated for changes to convertLatin1ToUTF8. 13 Removed unneeded "true" to get the strict version of convertUTF16ToUTF8, 14 since that is the default. Also updated for changes to CompletionResult. 15 16 * runtime/JSGlobalObjectFunctions.cpp: 17 (JSC::decode): Stop using UTF8SequenceLength, and instead use U8_COUNT_TRAIL_BYTES 18 and U8_MAX_LENGTH. Instead of decodeUTF8Sequence, use U8_NEXT. Also use U_IS_BMP, 19 U_IS_SUPPLEMENTARY, U16_LEAD, U16_TRAIL, and U_IS_SURROGATE instead of our own 20 equivalents, since these macros from ICU are correct and efficient. 21 22 * wasm/WasmParser.h: 23 (JSC::Wasm::Parser<SuccessType>::consumeUTF8String): Updated for changes to 24 convertUTF8ToUTF16. 25 1 26 2019-05-01 Shawn Roberts <sroberts@apple.com> 2 27 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
r244827 r244828 59 59 #include <wtf/dtoa.h> 60 60 #include <wtf/text/StringBuilder.h> 61 #include <wtf/unicode/UTF8Conversion.h>62 61 63 62 namespace JSC { 64 65 using namespace WTF::Unicode;66 63 67 64 const ASCIILiteral ObjectProtoCalledOnNullOrUndefinedError { "Object.prototype.__proto__ called on null or undefined"_s }; … … 185 182 if (k <= length - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) { 186 183 const char b0 = Lexer<CharType>::convertHex(p[1], p[2]); 187 const int sequenceLen = UTF8SequenceLength(b0);188 if ( sequenceLen &&k <= length - sequenceLen * 3) {184 const int sequenceLen = 1 + U8_COUNT_TRAIL_BYTES(b0); 185 if (k <= length - sequenceLen * 3) { 189 186 charLen = sequenceLen * 3; 190 char sequence[5];187 uint8_t sequence[U8_MAX_LENGTH]; 191 188 sequence[0] = b0; 192 189 for (int i = 1; i < sequenceLen; ++i) { … … 200 197 } 201 198 if (charLen != 0) { 202 sequence[sequenceLen] = 0; 203 const int character = decodeUTF8Sequence(sequence); 204 if (character < 0 || character >= 0x110000) 199 UChar32 character; 200 int32_t offset = 0; 201 U8_NEXT(sequence, offset, sequenceLen, character); 202 if (character < 0) 205 203 charLen = 0; 206 else if ( character >= 0x10000) {204 else if (!U_IS_BMP(character)) { 207 205 // Convert to surrogate pair. 208 builder.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10))); 209 u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF)); 210 } else 206 ASSERT(U_IS_SUPPLEMENTARY(character)); 207 builder.append(U16_LEAD(character)); 208 u = U16_TRAIL(character); 209 } else { 210 ASSERT(!U_IS_SURROGATE(character)); 211 211 u = static_cast<UChar>(character); 212 } 212 213 } 213 214 } -
trunk/Source/JavaScriptCore/wasm/WasmParser.h
r244827 r244828 163 163 UChar* bufferCurrent = bufferStart; 164 164 const char* stringCurrent = reinterpret_cast<const char*>(stringStart); 165 if ( WTF::Unicode::convertUTF8ToUTF16(&stringCurrent, reinterpret_cast<const char *>(stringStart + stringLength), &bufferCurrent, bufferCurrent + buffer.size()) != WTF::Unicode::conversionOK)165 if (!WTF::Unicode::convertUTF8ToUTF16(stringCurrent, reinterpret_cast<const char *>(stringStart + stringLength), &bufferCurrent, bufferCurrent + buffer.size())) 166 166 return false; 167 167 } -
trunk/Source/WTF/ChangeLog
r244827 r244828 1 2019-05-01 Darin Adler <darin@apple.com> 2 3 WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support 4 https://bugs.webkit.org/show_bug.cgi?id=195535 5 6 Reviewed by Alexey Proskuryakov. 7 8 * wtf/text/AtomicString.cpp: 9 (WTF::AtomicString::fromUTF8Internal): Added code to compute string length when the 10 end is nullptr; this behavior used to be implemented inside the 11 calculateStringHashAndLengthFromUTF8MaskingTop8Bits function. 12 13 * wtf/text/AtomicStringImpl.cpp: 14 (WTF::HashAndUTF8CharactersTranslator::translate): Updated for change to 15 convertUTF8ToUTF16. 16 17 * wtf/text/AtomicStringImpl.h: Took the WTF_EXPORT_PRIVATE off of the 18 AtomicStringImpl::addUTF8 function. This is used only inside a non-inlined function in 19 the AtomicString class and its behavior changed subtly in this patch; it's helpful 20 to document that it's not exported. 21 22 * wtf/text/StringImpl.cpp: 23 (WTF::StringImpl::utf8Impl): Don't pass "true" for strictness to convertUTF16ToUTF8 24 since strict is the default. Also updated for changes to ConversionResult. 25 (WTF::StringImpl::utf8ForCharacters): Updated for change to convertLatin1ToUTF8. 26 (WTF::StringImpl::tryGetUtf8ForRange const): Ditto. 27 28 * wtf/text/StringView.cpp: Removed uneeded include of UTF8Conversion.h. 29 30 * wtf/text/WTFString.cpp: 31 (WTF::String::fromUTF8): Updated for change to convertUTF8ToUTF16. 32 33 * wtf/unicode/UTF8Conversion.cpp: 34 (WTF::Unicode::inlineUTF8SequenceLengthNonASCII): Deleted. 35 (WTF::Unicode::inlineUTF8SequenceLength): Deleted. 36 (WTF::Unicode::UTF8SequenceLength): Deleted. 37 (WTF::Unicode::decodeUTF8Sequence): Deleted. 38 (WTF::Unicode::convertLatin1ToUTF8): Use U8_APPEND, enabling us to remove 39 almost everything in the function. Also changed resturn value to be a boolean 40 to indicate success since there is only one possible failure (target exhausted). 41 There is room for further simplification, since most callers have lengths rather 42 than end pointers for the source buffer, and all but one caller supplies a buffer 43 size known to be sufficient, so those don't need a return value, nor do they need 44 to pass an end of buffer pointer. 45 (WTF::Unicode::convertUTF16ToUTF8): Use U_IS_LEAD, U_IS_TRAIL, 46 U16_GET_SUPPLEMENTARY, U_IS_SURROGATE, and U8_APPEND. Also changed behavior 47 for non-strict mode so that unpaired surrogates will be turned into the 48 replacement character instead of invalid UTF-8 sequences, because U8_APPEND 49 won't create an invalid UTF-8 sequence, and because we don't need to do that 50 for any good reason at any call site. 51 (WTF::Unicode::isLegalUTF8): Deleted. 52 (WTF::Unicode::readUTF8Sequence): Deleted. 53 (WTF::Unicode::convertUTF8ToUTF16): Use U8_NEXT instead of 54 inlineUTF8SequenceLength, isLegalUTF8, and readUTF8Sequence. Use 55 U16_APPEND instead of lots of code that does the same thing. There is 56 room for further simplification since most callers don't need the "all ASCII" 57 feature and could probably pass the arguments in a more natural way. 58 (WTF::Unicode::calculateStringHashAndLengthFromUTF8MaskingTop8Bits): 59 Use U8_NEXT instead of isLegalUTF8, readUTF8Sequence, and various 60 error handling checks for things that are handled by U8_NEXT. Also removed 61 support for passing nullptr for end to specify a null-terminated string. 62 (WTF::Unicode::equalUTF16WithUTF8): Ditto. 63 64 * wtf/unicode/UTF8Conversion.h: Removed UTF8SequenceLength and 65 decodeUTF8Sequence. Changed the ConversionResult to match WebKit coding 66 style, with an eye toward perhaps removing it in the future. Changed 67 the convertUTF8ToUTF16 return value to a boolean and removed the "strict" 68 argument since no caller was passing false. Changed the convertLatin1ToUTF8 69 return value to a boolean. Tweaked comments. 70 1 71 2019-05-01 Shawn Roberts <sroberts@apple.com> 2 72 -
trunk/Source/WTF/wtf/text/AtomicString.cpp
r244827 r244828 114 114 } 115 115 116 AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const char* charactersEnd)116 AtomicString AtomicString::fromUTF8Internal(const char* start, const char* end) 117 117 { 118 auto impl = AtomicStringImpl::addUTF8(charactersStart, charactersEnd); 119 if (!impl) 120 return nullAtom(); 121 return impl.get(); 118 ASSERT(start); 119 120 // Caller needs to handle empty string. 121 ASSERT(!end || end > start); 122 ASSERT(end || start[0]); 123 124 return AtomicStringImpl::addUTF8(start, end ? end : start + std::strlen(start)); 122 125 } 123 126 124 127 #ifndef NDEBUG 128 125 129 void AtomicString::show() const 126 130 { 127 131 m_string.show(); 128 132 } 133 129 134 #endif 130 135 -
trunk/Source/WTF/wtf/text/AtomicStringImpl.cpp
r244827 r244828 220 220 bool isAllASCII; 221 221 const char* source = buffer.characters; 222 if ( convertUTF8ToUTF16(&source, source + buffer.length, &target, target + buffer.utf16Length, &isAllASCII) != conversionOK)222 if (!convertUTF8ToUTF16(source, source + buffer.length, &target, target + buffer.utf16Length, &isAllASCII)) 223 223 ASSERT_NOT_REACHED(); 224 224 -
trunk/Source/WTF/wtf/text/AtomicStringImpl.h
r244827 r244828 57 57 58 58 // Returns null if the input data contains an invalid UTF-8 sequence. 59 WTF_EXPORT_PRIVATE static RefPtr<AtomicStringImpl> addUTF8(const char* start, const char* end); 59 static RefPtr<AtomicStringImpl> addUTF8(const char* start, const char* end); 60 60 61 #if USE(CF) 61 62 WTF_EXPORT_PRIVATE static RefPtr<AtomicStringImpl> add(CFStringRef); -
trunk/Source/WTF/wtf/text/StringImpl.cpp
r244827 r244828 1757 1757 while (characters < charactersEnd) { 1758 1758 // Use strict conversion to detect unpaired surrogates. 1759 ConversionResult result = convertUTF16ToUTF8(&characters, charactersEnd, &buffer, bufferEnd, true);1760 ASSERT(result != targetExhausted);1759 auto result = convertUTF16ToUTF8(&characters, charactersEnd, &buffer, bufferEnd); 1760 ASSERT(result != TargetExhausted); 1761 1761 // Conversion fails when there is an unpaired surrogate. 1762 1762 // Put replacement character (U+FFFD) instead of the unpaired surrogate. 1763 if (result != conversionOK) {1763 if (result != ConversionOK) { 1764 1764 ASSERT((0xD800 <= *characters && *characters <= 0xDFFF)); 1765 1765 // There should be room left, since one UChar hasn't been converted. … … 1772 1772 bool strict = mode == StrictConversion; 1773 1773 const UChar* originalCharacters = characters; 1774 ConversionResultresult = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferSize, strict);1775 ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion1774 auto result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferSize, strict); 1775 ASSERT(result != TargetExhausted); // (length * 3) should be sufficient for any conversion 1776 1776 1777 1777 // Only produced from strict conversion. 1778 if (result == sourceIllegal) {1778 if (result == SourceIllegal) { 1779 1779 ASSERT(strict); 1780 1780 return UTF8ConversionError::IllegalSource; … … 1782 1782 1783 1783 // Check for an unconverted high surrogate. 1784 if (result == sourceExhausted) {1784 if (result == SourceExhausted) { 1785 1785 if (strict) 1786 1786 return UTF8ConversionError::SourceExhausted; … … 1810 1810 char* buffer = bufferVector.data(); 1811 1811 const LChar* source = characters; 1812 ConversionResult result= convertLatin1ToUTF8(&source, source + length, &buffer, buffer + bufferVector.size());1813 ASSERT_UNUSED( result, result != targetExhausted); // (length * 3) should be sufficient for any conversion1812 bool success = convertLatin1ToUTF8(&source, source + length, &buffer, buffer + bufferVector.size()); 1813 ASSERT_UNUSED(success, success); // (length * 3) should be sufficient for any conversion 1814 1814 return CString(bufferVector.data(), buffer - bufferVector.data()); 1815 1815 } … … 1855 1855 if (is8Bit()) { 1856 1856 const LChar* characters = this->characters8() + offset; 1857 1858 ConversionResult result = convertLatin1ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size()); 1859 ASSERT_UNUSED(result, result != targetExhausted); // (length * 3) should be sufficient for any conversion 1857 auto success = convertLatin1ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size()); 1858 ASSERT_UNUSED(success, success); // (length * 3) should be sufficient for any conversion 1860 1859 } else { 1861 1860 UTF8ConversionError error = utf8Impl(this->characters16() + offset, length, buffer, bufferVector.size(), mode); -
trunk/Source/WTF/wtf/text/StringView.cpp
r244827 r244828 36 36 #include <wtf/Optional.h> 37 37 #include <wtf/text/TextBreakIterator.h> 38 #include <wtf/unicode/UTF8Conversion.h>39 38 40 39 namespace WTF { 41 42 using namespace Unicode;43 40 44 41 bool StringView::containsIgnoringASCIICase(const StringView& matchString) const -
trunk/Source/WTF/wtf/text/WTFString.cpp
r244827 r244828 860 860 UChar* bufferCurrent = bufferStart; 861 861 const char* stringCurrent = reinterpret_cast<const char*>(stringStart); 862 if ( convertUTF8ToUTF16(&stringCurrent, reinterpret_cast<const char *>(stringStart + length), &bufferCurrent, bufferCurrent + buffer.size()) != conversionOK)862 if (!convertUTF8ToUTF16(stringCurrent, reinterpret_cast<const char *>(stringStart + length), &bufferCurrent, bufferCurrent + buffer.size())) 863 863 return String(); 864 864 -
trunk/Source/WTF/wtf/unicode/UTF8Conversion.cpp
r244827 r244828 1 1 /* 2 * Copyright (C) 2007 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2007-2019 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> 4 4 * … … 35 35 namespace Unicode { 36 36 37 inline int inlineUTF8SequenceLengthNonASCII(char b0)37 bool convertLatin1ToUTF8(const LChar** sourceStart, const LChar* sourceEnd, char** targetStart, char* targetEnd) 38 38 { 39 if ((b0 & 0xC0) != 0xC0) 40 return 0; 41 if ((b0 & 0xE0) == 0xC0) 42 return 2; 43 if ((b0 & 0xF0) == 0xE0) 44 return 3; 45 if ((b0 & 0xF8) == 0xF0) 46 return 4; 47 return 0; 39 const LChar* source; 40 char* target = *targetStart; 41 int i = 0; 42 for (source = *sourceStart; source < sourceEnd; ++source) { 43 UBool sawError = false; 44 // Work around bug in either Windows compiler or old version of ICU, where passing a uint8_t to 45 // U8_APPEND warns, by converting from uint8_t to a wider type. 46 UChar32 character = *source; 47 U8_APPEND(reinterpret_cast<uint8_t*>(target), i, targetEnd - *targetStart, character, sawError); 48 if (sawError) 49 return false; 50 } 51 *sourceStart = source; 52 *targetStart = target + i; 53 return true; 48 54 } 49 55 50 inline int inlineUTF8SequenceLength(char b0)56 ConversionResult convertUTF16ToUTF8(const UChar** sourceStart, const UChar* sourceEnd, char** targetStart, char* targetEnd, bool strict) 51 57 { 52 return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); 53 } 54 55 int UTF8SequenceLength(char b0) 56 { 57 return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); 58 } 59 60 int decodeUTF8Sequence(const char* sequence) 61 { 62 // Handle 0-byte sequences (never valid). 63 const unsigned char b0 = sequence[0]; 64 const int length = inlineUTF8SequenceLength(b0); 65 if (length == 0) 66 return -1; 67 68 // Handle 1-byte sequences (plain ASCII). 69 const unsigned char b1 = sequence[1]; 70 if (length == 1) { 71 if (b1) 72 return -1; 73 return b0; 74 } 75 76 // Handle 2-byte sequences. 77 if ((b1 & 0xC0) != 0x80) 78 return -1; 79 const unsigned char b2 = sequence[2]; 80 if (length == 2) { 81 if (b2) 82 return -1; 83 const int c = ((b0 & 0x1F) << 6) | (b1 & 0x3F); 84 if (c < 0x80) 85 return -1; 86 return c; 87 } 88 89 // Handle 3-byte sequences. 90 if ((b2 & 0xC0) != 0x80) 91 return -1; 92 const unsigned char b3 = sequence[3]; 93 if (length == 3) { 94 if (b3) 95 return -1; 96 const int c = ((b0 & 0xF) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F); 97 if (c < 0x800) 98 return -1; 99 // UTF-16 surrogates should never appear in UTF-8 data. 100 if (c >= 0xD800 && c <= 0xDFFF) 101 return -1; 102 return c; 103 } 104 105 // Handle 4-byte sequences. 106 if ((b3 & 0xC0) != 0x80) 107 return -1; 108 const unsigned char b4 = sequence[4]; 109 if (length == 4) { 110 if (b4) 111 return -1; 112 const int c = ((b0 & 0x7) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F); 113 if (c < 0x10000 || c > 0x10FFFF) 114 return -1; 115 return c; 116 } 117 118 return -1; 119 } 120 121 // Once the bits are split out into bytes of UTF-8, this is a mask OR-ed 122 // into the first byte, depending on how many bytes follow. There are 123 // as many entries in this table as there are UTF-8 sequence types. 124 // (I.e., one byte sequence, two byte... etc.). Remember that sequencs 125 // for *legal* UTF-8 will be 4 or fewer bytes total. 126 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 127 128 ConversionResult convertLatin1ToUTF8( 129 const LChar** sourceStart, const LChar* sourceEnd, 130 char** targetStart, char* targetEnd) 131 { 132 ConversionResult result = conversionOK; 133 const LChar* source = *sourceStart; 58 ConversionResult result = ConversionOK; 59 const UChar* source = *sourceStart; 134 60 char* target = *targetStart; 61 UBool sawError = false; 62 int i = 0; 135 63 while (source < sourceEnd) { 136 64 UChar32 ch; 137 unsigned short bytesToWrite = 0; 138 const UChar32 byteMask = 0xBF; 139 const UChar32 byteMark = 0x80; 140 const LChar* oldSource = source; // In case we have to back up because of target overflow. 141 ch = static_cast<unsigned short>(*source++); 142 143 // Figure out how many bytes the result will require 144 if (ch < (UChar32)0x80) 145 bytesToWrite = 1; 146 else 147 bytesToWrite = 2; 148 149 target += bytesToWrite; 150 if (target > targetEnd) { 151 source = oldSource; // Back up source pointer! 152 target -= bytesToWrite; 153 result = targetExhausted; 65 int j = 0; 66 U16_NEXT(source, j, sourceEnd - source, ch); 67 if (U_IS_SURROGATE(ch)) { 68 if (source + j == sourceEnd && U_IS_SURROGATE_LEAD(ch)) { 69 result = SourceExhausted; 70 break; 71 } 72 if (strict) { 73 result = SourceIllegal; 74 break; 75 } 76 ch = replacementCharacter; 77 } 78 U8_APPEND(reinterpret_cast<uint8_t*>(target), i, targetEnd - target, ch, sawError); 79 if (sawError) { 80 result = TargetExhausted; 154 81 break; 155 82 } 156 switch (bytesToWrite) { // note: everything falls through. 157 case 2: 158 *--target = (char)((ch | byteMark) & byteMask); 159 ch >>= 6; 160 FALLTHROUGH; 161 case 1: 162 *--target = (char)(ch | firstByteMark[bytesToWrite]); 163 } 164 target += bytesToWrite; 83 source += j; 165 84 } 166 85 *sourceStart = source; 167 *targetStart = target ;86 *targetStart = target + i; 168 87 return result; 169 88 } 170 89 171 ConversionResult convertUTF16ToUTF8( 172 const UChar** sourceStart, const UChar* sourceEnd, 173 char** targetStart, char* targetEnd, bool strict) 90 bool convertUTF8ToUTF16(const char* source, const char* sourceEnd, UChar** targetStart, UChar* targetEnd, bool* sourceAllASCII) 174 91 { 175 ConversionResult result = conversionOK; 176 const UChar* source = *sourceStart; 177 char* target = *targetStart; 178 while (source < sourceEnd) { 179 UChar32 ch; 180 unsigned short bytesToWrite = 0; 181 const UChar32 byteMask = 0xBF; 182 const UChar32 byteMark = 0x80; 183 const UChar* oldSource = source; // In case we have to back up because of target overflow. 184 ch = static_cast<unsigned short>(*source++); 185 // If we have a surrogate pair, convert to UChar32 first. 186 if (ch >= 0xD800 && ch <= 0xDBFF) { 187 // If the 16 bits following the high surrogate are in the source buffer... 188 if (source < sourceEnd) { 189 UChar32 ch2 = static_cast<unsigned short>(*source); 190 // If it's a low surrogate, convert to UChar32. 191 if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) { 192 ch = ((ch - 0xD800) << 10) + (ch2 - 0xDC00) + 0x0010000; 193 ++source; 194 } else if (strict) { // it's an unpaired high surrogate 195 --source; // return to the illegal value itself 196 result = sourceIllegal; 197 break; 198 } 199 } else { // We don't have the 16 bits following the high surrogate. 200 --source; // return to the high surrogate 201 result = sourceExhausted; 202 break; 203 } 204 } else if (strict) { 205 // UTF-16 surrogate values are illegal in UTF-32 206 if (ch >= 0xDC00 && ch <= 0xDFFF) { 207 --source; // return to the illegal value itself 208 result = sourceIllegal; 209 break; 210 } 211 } 212 // Figure out how many bytes the result will require 213 if (ch < (UChar32)0x80) { 214 bytesToWrite = 1; 215 } else if (ch < (UChar32)0x800) { 216 bytesToWrite = 2; 217 } else if (ch < (UChar32)0x10000) { 218 bytesToWrite = 3; 219 } else if (ch < (UChar32)0x110000) { 220 bytesToWrite = 4; 221 } else { 222 bytesToWrite = 3; 223 ch = replacementCharacter; 224 } 225 226 target += bytesToWrite; 227 if (target > targetEnd) { 228 source = oldSource; // Back up source pointer! 229 target -= bytesToWrite; 230 result = targetExhausted; 231 break; 232 } 233 switch (bytesToWrite) { // note: everything falls through. 234 case 4: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6; FALLTHROUGH; 235 case 3: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6; FALLTHROUGH; 236 case 2: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6; FALLTHROUGH; 237 case 1: *--target = (char)(ch | firstByteMark[bytesToWrite]); 238 } 239 target += bytesToWrite; 92 RELEASE_ASSERT(sourceEnd - source <= std::numeric_limits<int>::max()); 93 UBool error = false; 94 UChar* target = *targetStart; 95 UChar32 orAllData = 0; 96 int targetOffset = 0; 97 for (int sourceOffset = 0; sourceOffset < sourceEnd - source; ) { 98 UChar32 character; 99 U8_NEXT(reinterpret_cast<const uint8_t*>(source), sourceOffset, sourceEnd - source, character); 100 if (character < 0) 101 return false; 102 U16_APPEND(target, targetOffset, targetEnd - target, character, error); 103 if (error) 104 return false; 105 orAllData |= character; 240 106 } 241 *sourceStart = source; 242 *targetStart = target; 243 return result; 244 } 245 246 // This must be called with the length pre-determined by the first byte. 247 // If presented with a length > 4, this returns false. The Unicode 248 // definition of UTF-8 goes up to 4-byte sequences. 249 static bool isLegalUTF8(const unsigned char* source, int length) 250 { 251 unsigned char a; 252 const unsigned char* srcptr = source + length; 253 switch (length) { 254 default: return false; 255 // Everything else falls through when "true"... 256 case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; FALLTHROUGH; 257 case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; FALLTHROUGH; 258 case 2: if ((a = (*--srcptr)) > 0xBF) return false; 259 260 switch (*source) { 261 // no fall-through in this inner switch 262 case 0xE0: if (a < 0xA0) return false; break; 263 case 0xED: if (a > 0x9F) return false; break; 264 case 0xF0: if (a < 0x90) return false; break; 265 case 0xF4: if (a > 0x8F) return false; break; 266 default: if (a < 0x80) return false; 267 } 268 FALLTHROUGH; 269 270 case 1: if (*source >= 0x80 && *source < 0xC2) return false; 271 } 272 if (*source > 0xF4) 273 return false; 107 *targetStart = target + targetOffset; 108 if (sourceAllASCII) 109 *sourceAllASCII = isASCII(orAllData); 274 110 return true; 275 }276 277 // Magic values subtracted from a buffer value during UTF8 conversion.278 // This table contains as many values as there might be trailing bytes279 // in a UTF-8 sequence.280 static const UChar32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, static_cast<UChar32>(0xFA082080UL), static_cast<UChar32>(0x82082080UL) };281 282 static inline UChar32 readUTF8Sequence(const char*& sequence, unsigned length)283 {284 UChar32 character = 0;285 286 // The cases all fall through.287 switch (length) {288 case 6: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;289 case 5: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;290 case 4: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;291 case 3: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;292 case 2: character += static_cast<unsigned char>(*sequence++); character <<= 6; FALLTHROUGH;293 case 1: character += static_cast<unsigned char>(*sequence++);294 }295 296 return character - offsetsFromUTF8[length - 1];297 }298 299 ConversionResult convertUTF8ToUTF16(300 const char** sourceStart, const char* sourceEnd,301 UChar** targetStart, UChar* targetEnd, bool* sourceAllASCII, bool strict)302 {303 ConversionResult result = conversionOK;304 const char* source = *sourceStart;305 UChar* target = *targetStart;306 UChar orAllData = 0;307 while (source < sourceEnd) {308 int utf8SequenceLength = inlineUTF8SequenceLength(*source);309 if (sourceEnd - source < utf8SequenceLength) {310 result = sourceExhausted;311 break;312 }313 // Do this check whether lenient or strict314 if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(source), utf8SequenceLength)) {315 result = sourceIllegal;316 break;317 }318 319 UChar32 character = readUTF8Sequence(source, utf8SequenceLength);320 321 if (target >= targetEnd) {322 source -= utf8SequenceLength; // Back up source pointer!323 result = targetExhausted;324 break;325 }326 327 if (U_IS_BMP(character)) {328 // UTF-16 surrogate values are illegal in UTF-32329 if (U_IS_SURROGATE(character)) {330 if (strict) {331 source -= utf8SequenceLength; // return to the illegal value itself332 result = sourceIllegal;333 break;334 } else {335 *target++ = replacementCharacter;336 orAllData |= replacementCharacter;337 }338 } else {339 *target++ = character; // normal case340 orAllData |= character;341 }342 } else if (U_IS_SUPPLEMENTARY(character)) {343 // target is a character in range 0xFFFF - 0x10FFFF344 if (target + 1 >= targetEnd) {345 source -= utf8SequenceLength; // Back up source pointer!346 result = targetExhausted;347 break;348 }349 *target++ = U16_LEAD(character);350 *target++ = U16_TRAIL(character);351 orAllData = 0xffff;352 } else {353 if (strict) {354 source -= utf8SequenceLength; // return to the start355 result = sourceIllegal;356 break; // Bail out; shouldn't continue357 } else {358 *target++ = replacementCharacter;359 orAllData |= replacementCharacter;360 }361 }362 }363 *sourceStart = source;364 *targetStart = target;365 366 if (sourceAllASCII)367 *sourceAllASCII = !(orAllData & ~0x7f);368 369 return result;370 111 } 371 112 372 113 unsigned calculateStringHashAndLengthFromUTF8MaskingTop8Bits(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length) 373 114 { 374 if (!data)375 return 0;376 377 115 StringHasher stringHasher; 378 dataLength = 0;379 116 utf16Length = 0; 380 117 381 while (data < dataEnd || (!dataEnd && *data)) { 382 if (isASCII(*data)) { 383 stringHasher.addCharacter(*data++); 384 dataLength++; 385 utf16Length++; 386 continue; 387 } 388 389 int utf8SequenceLength = inlineUTF8SequenceLengthNonASCII(*data); 390 dataLength += utf8SequenceLength; 391 392 if (!dataEnd) { 393 for (int i = 1; i < utf8SequenceLength; ++i) { 394 if (!data[i]) 395 return 0; 396 } 397 } else if (dataEnd - data < utf8SequenceLength) 118 int inputOffset = 0; 119 int inputLength = dataEnd - data; 120 while (inputOffset < inputLength) { 121 UChar32 character; 122 U8_NEXT(reinterpret_cast<const uint8_t*>(data), inputOffset, inputLength, character); 123 if (character < 0) 398 124 return 0; 399 125 400 if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(data), utf8SequenceLength))401 return 0;402 403 UChar32 character = readUTF8Sequence(data, utf8SequenceLength);404 ASSERT(!isASCII(character));405 406 126 if (U_IS_BMP(character)) { 407 // UTF-16 surrogate values are illegal in UTF-32 408 if (U_IS_SURROGATE(character)) 409 return 0; 410 stringHasher.addCharacter(static_cast<UChar>(character)); // normal case 127 ASSERT(!U_IS_SURROGATE(character)); 128 stringHasher.addCharacter(character); 411 129 utf16Length++; 412 } else if (U_IS_SUPPLEMENTARY(character)){413 stringHasher.addCharacters(static_cast<UChar>(U16_LEAD(character)),414 static_cast<UChar>(U16_TRAIL(character)));130 } else { 131 ASSERT(U_IS_SUPPLEMENTARY(character)); 132 stringHasher.addCharacters(U16_LEAD(character), U16_TRAIL(character)); 415 133 utf16Length += 2; 416 } else 417 return 0; 134 } 418 135 } 419 136 137 dataLength = inputOffset; 420 138 return stringHasher.hashWithTop8BitsMasked(); 421 139 } … … 424 142 { 425 143 while (b < bEnd) { 426 if (isASCII(*a) || isASCII(*b)) { 427 if (*a++ != *b++) 428 return false; 429 continue; 430 } 431 432 int utf8SequenceLength = inlineUTF8SequenceLengthNonASCII(*b); 433 434 if (bEnd - b < utf8SequenceLength) 144 int offset = 0; 145 UChar32 character; 146 U8_NEXT(reinterpret_cast<const uint8_t*>(b), offset, bEnd - b, character); 147 if (character < 0) 435 148 return false; 436 437 if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(b), utf8SequenceLength)) 438 return false; 439 440 UChar32 character = readUTF8Sequence(b, utf8SequenceLength); 441 ASSERT(!isASCII(character)); 149 b += offset; 442 150 443 151 if (U_IS_BMP(character)) { 444 // UTF-16 surrogate values are illegal in UTF-32 445 if (U_IS_SURROGATE(character)) 446 return false; 152 ASSERT(!U_IS_SURROGATE(character)); 447 153 if (*a++ != character) 448 154 return false; 449 } else if (U_IS_SUPPLEMENTARY(character)) { 155 } else { 156 ASSERT(U_IS_SUPPLEMENTARY(character)); 450 157 if (*a++ != U16_LEAD(character)) 451 158 return false; 452 159 if (*a++ != U16_TRAIL(character)) 453 160 return false; 454 } else 455 return false; 161 } 456 162 } 457 163 -
trunk/Source/WTF/wtf/unicode/UTF8Conversion.h
r244827 r244828 1 1 /* 2 * Copyright (C) 2007 Apple Inc.All rights reserved.2 * Copyright (C) 2007-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 32 32 namespace Unicode { 33 33 34 // Given a first byte, gives the length of the UTF-8 sequence it begins. 35 // Returns 0 for bytes that are not legal starts of UTF-8 sequences. 36 // Only allows sequences of up to 4 bytes, since that works for all Unicode characters (U-00000000 to U-0010FFFF). 37 WTF_EXPORT_PRIVATE int UTF8SequenceLength(char); 34 enum ConversionResult { 35 ConversionOK, // conversion successful 36 SourceExhausted, // partial character in source, but hit end 37 TargetExhausted, // insufficient room in target for conversion 38 SourceIllegal // source sequence is illegal/malformed 39 }; 38 40 39 // Takes a null-terminated C-style string with a UTF-8 sequence in it and converts it to a character. 40 // Only allows Unicode characters (U-00000000 to U-0010FFFF). 41 // Returns -1 if the sequence is not valid (including presence of extra bytes). 42 WTF_EXPORT_PRIVATE int decodeUTF8Sequence(const char*); 41 // Conversion functions are strict, except for convertUTF16ToUTF8, which takes 42 // "strict" argument. When strict, both illegal sequences and unpaired surrogates 43 // will cause an error. When not, illegal sequences and unpaired surrogates are 44 // converted to the replacement character, except for an unpaired lead surrogate 45 // at the end of the source, which will instead cause a SourceExhausted error. 43 46 44 typedef enum { 45 conversionOK, // conversion successful 46 sourceExhausted, // partial character in source, but hit end 47 targetExhausted, // insuff. room in target for conversion 48 sourceIllegal // source sequence is illegal/malformed 49 } ConversionResult; 47 WTF_EXPORT_PRIVATE bool convertUTF8ToUTF16(const char* sourceStart, const char* sourceEnd, UChar** targetStart, UChar* targetEnd, bool* isSourceAllASCII = nullptr); 48 WTF_EXPORT_PRIVATE bool convertLatin1ToUTF8(const LChar** sourceStart, const LChar* sourceEnd, char** targetStart, char* targetEnd); 49 WTF_EXPORT_PRIVATE ConversionResult convertUTF16ToUTF8(const UChar** sourceStart, const UChar* sourceEnd, char** targetStart, char* targetEnd, bool strict = true); 50 50 51 // These conversion functions take a "strict" argument. When this 52 // flag is set to strict, both irregular sequences and isolated surrogates 53 // will cause an error. When the flag is set to lenient, both irregular 54 // sequences and isolated surrogates are converted. 55 // 56 // Whether the flag is strict or lenient, all illegal sequences will cause 57 // an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, 58 // or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code 59 // must check for illegal sequences. 60 // 61 // When the flag is set to lenient, characters over 0x10FFFF are converted 62 // to the replacement character; otherwise (when the flag is set to strict) 63 // they constitute an error. 51 WTF_EXPORT_PRIVATE unsigned calculateStringHashAndLengthFromUTF8MaskingTop8Bits(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length); 64 52 65 WTF_EXPORT_PRIVATE ConversionResult convertUTF8ToUTF16( 66 const char** sourceStart, const char* sourceEnd, 67 UChar** targetStart, UChar* targetEnd, bool* isSourceAllASCII = 0, bool strict = true); 68 69 WTF_EXPORT_PRIVATE ConversionResult convertLatin1ToUTF8( 70 const LChar** sourceStart, const LChar* sourceEnd, 71 char** targetStart, char* targetEnd); 72 73 WTF_EXPORT_PRIVATE ConversionResult convertUTF16ToUTF8( 74 const UChar** sourceStart, const UChar* sourceEnd, 75 char** targetStart, char* targetEnd, bool strict = true); 76 77 WTF_EXPORT_PRIVATE unsigned calculateStringHashAndLengthFromUTF8MaskingTop8Bits(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length); 78 79 // The caller of these functions already knows that the lengths are the same, so we omit an end argument for UTF-16 and Latin-1. 80 bool equalUTF16WithUTF8(const UChar* stringInUTF16, const char* stringInUTF8, const char* stringInUTF8End); 81 bool equalLatin1WithUTF8(const LChar* stringInLatin1, const char* stringInUTF8, const char* stringInUTF8End); 53 // Callers of these functions must check that the lengths are the same; accordingly we omit an end argument for UTF-16 and Latin-1. 54 bool equalUTF16WithUTF8(const UChar* stringInUTF16, const char* stringInUTF8, const char* stringInUTF8End); 55 bool equalLatin1WithUTF8(const LChar* stringInLatin1, const char* stringInUTF8, const char* stringInUTF8End); 82 56 83 57 } // namespace Unicode -
trunk/Source/WebCore/ChangeLog
r244827 r244828 1 2019-05-01 Darin Adler <darin@apple.com> 2 3 WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support 4 https://bugs.webkit.org/show_bug.cgi?id=195535 5 6 Reviewed by Alexey Proskuryakov. 7 8 * platform/SharedBuffer.cpp: 9 (WebCore::utf8Buffer): Removed unnecessary "strict" argument to convertUTF16ToUTF8 since 10 that is the default behavior. Also updated for changes to return values. 11 12 * xml/XSLTProcessorLibxslt.cpp: 13 (WebCore::writeToStringBuilder): Removed unnecessary use of StringBuffer for a temporary 14 buffer for characters. Rewrote to use U8_NEXT and U16_APPEND directly. 15 16 * xml/parser/XMLDocumentParserLibxml2.cpp: 17 (WebCore::convertUTF16EntityToUTF8): Updated for changes to CompletionResult. 18 1 19 2019-05-01 Shawn Roberts <sroberts@apple.com> 2 20 -
trunk/Source/WebCore/ChangeLog-2010-12-06
r244826 r244828 95191 95191 https://bugs.webkit.org/show_bug.cgi?id=42768 95192 95192 95193 Normalize path separators for the script API by conver ing \'s to /'s.95193 Normalize path separators for the script API by converting \'s to /'s. 95194 95194 95195 95195 Covered by input-file-directory-upload.html -
trunk/Source/WebCore/ChangeLog-2013-04-24
r244826 r244828 42511 42511 * platform/graphics/chromium/GraphicsLayerChromium.cpp: 42512 42512 (WebCore::transformToSkMatrix44): 42513 Utility for conver ing a WebCore::TransformationMatrix to an SkMatrix44.42513 Utility for converting a WebCore::TransformationMatrix to an SkMatrix44. 42514 42514 Will move to a more common location once it gets more callers. 42515 42515 (WebCore::GraphicsLayerChromium::updateTransform): -
trunk/Source/WebCore/platform/SharedBuffer.cpp
r244827 r244828 335 335 // Convert to runs of 8-bit characters. 336 336 char* p = buffer.data(); 337 WTF::Unicode::ConversionResult result;338 337 if (length) { 339 338 if (string.is8Bit()) { 340 339 const LChar* d = string.characters8(); 341 result = WTF::Unicode::convertLatin1ToUTF8(&d, d + length, &p, p + buffer.size()); 340 if (!WTF::Unicode::convertLatin1ToUTF8(&d, d + length, &p, p + buffer.size())) 341 return nullptr; 342 342 } else { 343 343 const UChar* d = string.characters16(); 344 result = WTF::Unicode::convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), true); 344 if (WTF::Unicode::convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size()) != WTF::Unicode::ConversionOK) 345 return nullptr; 345 346 } 346 if (result != WTF::Unicode::conversionOK)347 return nullptr;348 347 } 349 348 -
trunk/Source/WebCore/xml/XSLTProcessorLibxslt.cpp
r244827 r244828 49 49 #include <libxslt/xsltutils.h> 50 50 #include <wtf/Assertions.h> 51 #include <wtf/text/StringBuffer.h>52 #include <wtf/unicode/UTF8Conversion.h>53 51 54 52 #if OS(DARWIN) && !PLATFORM(GTK) … … 160 158 } 161 159 162 static int writeToStringBuilder(void* context, const char* buffer, int len )160 static int writeToStringBuilder(void* context, const char* buffer, int length) 163 161 { 164 162 StringBuilder& resultOutput = *static_cast<StringBuilder*>(context); 165 163 166 if (!len) 167 return 0; 168 169 StringBuffer<UChar> stringBuffer(len); 170 UChar* bufferUChar = stringBuffer.characters(); 171 UChar* bufferUCharEnd = bufferUChar + len; 172 173 const char* stringCurrent = buffer; 174 WTF::Unicode::ConversionResult result = WTF::Unicode::convertUTF8ToUTF16(&stringCurrent, buffer + len, &bufferUChar, bufferUCharEnd); 175 if (result != WTF::Unicode::conversionOK && result != WTF::Unicode::sourceExhausted) { 176 ASSERT_NOT_REACHED(); 177 return -1; 178 } 179 180 int utf16Length = bufferUChar - stringBuffer.characters(); 181 resultOutput.append(stringBuffer.characters(), utf16Length); 182 return stringCurrent - buffer; 164 // FIXME: Consider ways to make this more efficient by moving it into a 165 // StringBuilder::appendUTF8 function, and then optimizing to not need a 166 // Vector<UChar> and possibly optimize cases that can produce 8-bit Latin-1 167 // strings, but that would need to be sophisticated about not processing 168 // trailing incomplete sequences and communicating that to the caller. 169 170 Vector<UChar> outputBuffer(length); 171 172 UBool error = false; 173 int inputOffset = 0; 174 int outputOffset = 0; 175 while (inputOffset < length) { 176 UChar32 character; 177 int nextInputOffset = inputOffset; 178 U8_NEXT(reinterpret_cast<const uint8_t*>(buffer), nextInputOffset, length, character); 179 if (character < 0) { 180 if (nextInputOffset == length) 181 break; 182 ASSERT_NOT_REACHED(); 183 return -1; 184 } 185 inputOffset = nextInputOffset; 186 U16_APPEND(outputBuffer.data(), outputOffset, length, character, error); 187 if (error) { 188 ASSERT_NOT_REACHED(); 189 return -1; 190 } 191 } 192 193 resultOutput.append(outputBuffer.data(), outputOffset); 194 return inputOffset; 183 195 } 184 196 -
trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp
r244827 r244828 1155 1155 const char* originalTarget = target; 1156 1156 auto conversionResult = WTF::Unicode::convertUTF16ToUTF8(&utf16Entity, utf16Entity + numberOfCodeUnits, &target, target + targetSize); 1157 if (conversionResult != WTF::Unicode:: conversionOK)1157 if (conversionResult != WTF::Unicode::ConversionOK) 1158 1158 return 0; 1159 1159 -
trunk/Source/WebKit/ChangeLog
r244827 r244828 1 2019-05-01 Darin Adler <darin@apple.com> 2 3 WebKit has too much of its own UTF-8 code and should rely more on ICU's UTF-8 support 4 https://bugs.webkit.org/show_bug.cgi?id=195535 5 6 Reviewed by Alexey Proskuryakov. 7 8 * Shared/API/APIString.h: Removed uneeded includes and also switched to #pragma once. 9 10 * Shared/API/c/WKString.cpp: Moved include of UTF8Conversion.h here. 11 (WKStringGetUTF8CStringImpl): Updated for changes to return values. 12 1 13 2019-05-01 Shawn Roberts <sroberts@apple.com> 2 14 -
trunk/Source/WebKit/Shared/API/APIString.h
r244827 r244828 24 24 */ 25 25 26 #ifndef APIString_h 27 #define APIString_h 26 #pragma once 28 27 29 28 #include "APIObject.h" 30 #include <wtf/Ref.h>31 29 #include <wtf/text/StringView.h> 32 #include <wtf/text/WTFString.h>33 #include <wtf/unicode/UTF8Conversion.h>34 30 35 31 namespace API { … … 76 72 77 73 } // namespace WebKit 78 79 #endif // APIString_h -
trunk/Source/WebKit/Shared/API/c/WKString.cpp
r244827 r244828 31 31 #include <JavaScriptCore/InitializeThreading.h> 32 32 #include <JavaScriptCore/OpaqueJSString.h> 33 #include <wtf/unicode/UTF8Conversion.h> 33 34 34 35 WKTypeID WKStringGetTypeID() … … 79 80 80 81 char* p = buffer; 81 WTF::Unicode::ConversionResult result;82 82 83 83 if (stringView.is8Bit()) { 84 84 const LChar* characters = stringView.characters8(); 85 result = WTF::Unicode::convertLatin1ToUTF8(&characters, characters + stringView.length(), &p, p + bufferSize - 1); 85 if (!WTF::Unicode::convertLatin1ToUTF8(&characters, characters + stringView.length(), &p, p + bufferSize - 1)) 86 return 0; 86 87 } else { 87 88 const UChar* characters = stringView.characters16(); 88 result = WTF::Unicode::convertUTF16ToUTF8(&characters, characters + stringView.length(), &p, p + bufferSize - 1, strict); 89 auto result = WTF::Unicode::convertUTF16ToUTF8(&characters, characters + stringView.length(), &p, p + bufferSize - 1, strict); 90 if (result != WTF::Unicode::ConversionOK && result != WTF::Unicode::TargetExhausted) 91 return 0; 89 92 } 90 91 if (result != WTF::Unicode::conversionOK && result != WTF::Unicode::targetExhausted)92 return 0;93 93 94 94 *p++ = '\0';
Note:
See TracChangeset
for help on using the changeset viewer.