| OLD | NEW |
| (Empty) | |
| 1 From 8b5285054be530e5a938231cff4018de7dbc6e0b Mon Sep 17 00:00:00 2001 |
| 2 From: Scott Hess <shess@chromium.org> |
| 3 Date: Mon, 1 Feb 2016 17:07:24 -0800 |
| 4 Subject: [PATCH 12/13] [backport] Fix buffer overrun in ICU extension's LIKE |
| 5 function. |
| 6 |
| 7 Original Chromium CL at https://codereview.chromium.org/1643803003 |
| 8 |
| 9 "Use safe macros for UTF-8 iteration in sqlite" |
| 10 |
| 11 SQLite interpretation: https://www.sqlite.org/src/info/424b7aee3310b978 |
| 12 |
| 13 "Fix the ICU extension LIKE function so that it does not read past the |
| 14 end of a buffer if it it passed malformed utf-8." |
| 15 |
| 16 BUG=575205 |
| 17 --- |
| 18 third_party/sqlite/src/ext/icu/icu.c | 64 ++++++++++++++++++++++++++---------- |
| 19 1 file changed, 47 insertions(+), 17 deletions(-) |
| 20 |
| 21 diff --git a/third_party/sqlite/src/ext/icu/icu.c b/third_party/sqlite/src/ext/i
cu/icu.c |
| 22 index a2ff492..5654366 100644 |
| 23 --- a/third_party/sqlite/src/ext/icu/icu.c |
| 24 +++ b/third_party/sqlite/src/ext/icu/icu.c |
| 25 @@ -61,6 +61,38 @@ static void xFree(void *p){ |
| 26 } |
| 27 |
| 28 /* |
| 29 +** This lookup table is used to help decode the first byte of |
| 30 +** a multi-byte UTF8 character. It is copied here from SQLite source |
| 31 +** code file utf8.c. |
| 32 +*/ |
| 33 +static const unsigned char icuUtf8Trans1[] = { |
| 34 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 35 + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 36 + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 37 + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, |
| 38 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 39 + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 40 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 41 + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, |
| 42 +}; |
| 43 + |
| 44 +#define SQLITE_ICU_READ_UTF8(zIn, c) \ |
| 45 + c = *(zIn++); \ |
| 46 + if( c>=0xc0 ){ \ |
| 47 + c = icuUtf8Trans1[c-0xc0]; \ |
| 48 + while( (*zIn & 0xc0)==0x80 ){ \ |
| 49 + c = (c<<6) + (0x3f & *(zIn++)); \ |
| 50 + } \ |
| 51 + } |
| 52 + |
| 53 +#define SQLITE_ICU_SKIP_UTF8(zIn) \ |
| 54 + assert( *zIn ); \ |
| 55 + if( *(zIn++)>=0xc0 ){ \ |
| 56 + while( (*zIn & 0xc0)==0x80 ){zIn++;} \ |
| 57 + } |
| 58 + |
| 59 + |
| 60 +/* |
| 61 ** Compare two UTF-8 strings for equality where the first string is |
| 62 ** a "LIKE" expression. Return true (1) if they are the same and |
| 63 ** false (0) if they are different. |
| 64 @@ -73,16 +105,14 @@ static int icuLikeCompare( |
| 65 static const int MATCH_ONE = (UChar32)'_'; |
| 66 static const int MATCH_ALL = (UChar32)'%'; |
| 67 |
| 68 - int iPattern = 0; /* Current byte index in zPattern */ |
| 69 - int iString = 0; /* Current byte index in zString */ |
| 70 - |
| 71 int prevEscape = 0; /* True if the previous character was uEsc */ |
| 72 |
| 73 - while( zPattern[iPattern]!=0 ){ |
| 74 + while( 1 ){ |
| 75 |
| 76 /* Read (and consume) the next character from the input pattern. */ |
| 77 UChar32 uPattern; |
| 78 - U8_NEXT_UNSAFE(zPattern, iPattern, uPattern); |
| 79 + SQLITE_ICU_READ_UTF8(zPattern, uPattern); |
| 80 + if( uPattern==0 ) break; |
| 81 |
| 82 /* There are now 4 possibilities: |
| 83 ** |
| 84 @@ -99,28 +129,28 @@ static int icuLikeCompare( |
| 85 ** MATCH_ALL. For each MATCH_ONE, skip one character in the |
| 86 ** test string. |
| 87 */ |
| 88 - while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){ |
| 89 + while( (c=*zPattern) == MATCH_ALL || c == MATCH_ONE ){ |
| 90 if( c==MATCH_ONE ){ |
| 91 - if( zString[iString]==0 ) return 0; |
| 92 - U8_FWD_1_UNSAFE(zString, iString); |
| 93 + if( *zString==0 ) return 0; |
| 94 + SQLITE_ICU_SKIP_UTF8(zString); |
| 95 } |
| 96 - iPattern++; |
| 97 + zPattern++; |
| 98 } |
| 99 |
| 100 - if( zPattern[iPattern]==0 ) return 1; |
| 101 + if( *zPattern==0 ) return 1; |
| 102 |
| 103 - while( zString[iString] ){ |
| 104 - if( icuLikeCompare(&zPattern[iPattern], &zString[iString], uEsc) ){ |
| 105 + while( *zString ){ |
| 106 + if( icuLikeCompare(zPattern, zString, uEsc) ){ |
| 107 return 1; |
| 108 } |
| 109 - U8_FWD_1_UNSAFE(zString, iString); |
| 110 + SQLITE_ICU_SKIP_UTF8(zString); |
| 111 } |
| 112 return 0; |
| 113 |
| 114 }else if( !prevEscape && uPattern==MATCH_ONE ){ |
| 115 /* Case 2. */ |
| 116 - if( zString[iString]==0 ) return 0; |
| 117 - U8_FWD_1_UNSAFE(zString, iString); |
| 118 + if( *zString==0 ) return 0; |
| 119 + SQLITE_ICU_SKIP_UTF8(zString); |
| 120 |
| 121 }else if( !prevEscape && uPattern==uEsc){ |
| 122 /* Case 3. */ |
| 123 @@ -129,7 +159,7 @@ static int icuLikeCompare( |
| 124 }else{ |
| 125 /* Case 4. */ |
| 126 UChar32 uString; |
| 127 - U8_NEXT_UNSAFE(zString, iString, uString); |
| 128 + SQLITE_ICU_READ_UTF8(zString, uString); |
| 129 uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT); |
| 130 uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT); |
| 131 if( uString!=uPattern ){ |
| 132 @@ -139,7 +169,7 @@ static int icuLikeCompare( |
| 133 } |
| 134 } |
| 135 |
| 136 - return zString[iString]==0; |
| 137 + return *zString==0; |
| 138 } |
| 139 |
| 140 /* |
| 141 -- |
| 142 2.7.0 |
| 143 |
| OLD | NEW |