View | Details | Raw Unified | Return to bug 218788 | Differences between
and this patch

Collapse All | Expand All

(-)./Makefile (-1 / +1 lines)
Lines 3-9 Link Here
3
3
4
PORTNAME=	icu
4
PORTNAME=	icu
5
DISTVERSION=	58_2
5
DISTVERSION=	58_2
6
PORTREVISION?=	1 # keep for icu-lx
6
PORTREVISION?=	2 # keep for icu-lx
7
PORTEPOCH?=	1
7
PORTEPOCH?=	1
8
CATEGORIES?=	devel
8
CATEGORIES?=	devel
9
MASTER_SITES=	http://download.icu-project.org/files/icu4c/${PORTVERSION}/
9
MASTER_SITES=	http://download.icu-project.org/files/icu4c/${PORTVERSION}/
(-)./files/patch-r182036 (+170 lines)
Line 0 Link Here
1
--- common/utext.cpp.orig	2016-06-15 18:58:17 UTC
2
+++ common/utext.cpp
3
@@ -847,9 +847,15 @@ U_CDECL_END
4
 //------------------------------------------------------------------------------
5
 
6
 // Chunk size.
7
-//     Must be less than 85, because of byte mapping from UChar indexes to native indexes.
8
-//     Worst case is three native bytes to one UChar.  (Supplemenaries are 4 native bytes
9
-//     to two UChars.)
10
+//     Must be less than 42  (256/6), because of byte mapping from UChar indexes to native indexes.
11
+//     Worst case there are six UTF-8 bytes per UChar.
12
+//         obsolete 6 byte form fd + 5 trails maps to fffd
13
+//         obsolete 5 byte form fc + 4 trails maps to fffd
14
+//         non-shortest 4 byte forms maps to fffd
15
+//         normal supplementaries map to a pair of utf-16, two utf8 bytes per utf-16 unit
16
+//     mapToUChars array size must allow for the worst case, 6.
17
+//     This could be brought down to 4, by treating fd and fc as pure illegal,
18
+//     rather than obsolete lead bytes. But that is not compatible with the utf-8 access macros.
19
 //
20
 enum { UTF8_TEXT_CHUNK_SIZE=32 };
21
 
22
@@ -889,7 +895,7 @@ struct UTF8Buf {
23
                                                      //  Requires two extra slots,
24
                                                      //    one for a supplementary starting in the last normal position,
25
                                                      //    and one for an entry for the buffer limit position.
26
-    uint8_t   mapToUChars[UTF8_TEXT_CHUNK_SIZE*3+6]; // Map native offset from bufNativeStart to
27
+    uint8_t   mapToUChars[UTF8_TEXT_CHUNK_SIZE*6+6]; // Map native offset from bufNativeStart to
28
                                                      //   correspoding offset in filled part of buf.
29
     int32_t   align;
30
 };
31
@@ -1032,6 +1038,7 @@ utf8TextAccess(UText *ut, int64_t index,
32
             // Requested index is in this buffer.
33
             u8b = (UTF8Buf *)ut->p;   // the current buffer
34
             mapIndex = ix - u8b->toUCharsMapStart;
35
+            U_ASSERT(mapIndex < (int32_t)sizeof(UTF8Buf::mapToUChars));
36
             ut->chunkOffset = u8b->mapToUChars[mapIndex] - u8b->bufStartIdx;
37
             return TRUE;
38
 
39
@@ -1298,6 +1305,10 @@ fillReverse:
40
         // Can only do this if the incoming index is somewhere in the interior of the string.
41
         //   If index is at the end, there is no character there to look at.
42
         if (ix != ut->b) {
43
+            // Note: this function will only move the index back if it is on a trail byte
44
+            //       and there is a preceding lead byte and the sequence from the lead
45
+            //       through this trail could be part of a valid UTF-8 sequence
46
+            //       Otherwise the index remains unchanged.
47
             U8_SET_CP_START(s8, 0, ix);
48
         }
49
 
50
@@ -1311,7 +1322,10 @@ fillReverse:
51
         UChar   *buf = u8b->buf;
52
         uint8_t *mapToNative = u8b->mapToNative;
53
         uint8_t *mapToUChars = u8b->mapToUChars;
54
-        int32_t  toUCharsMapStart = ix - (UTF8_TEXT_CHUNK_SIZE*3 + 1);
55
+        int32_t  toUCharsMapStart = ix - sizeof(UTF8Buf::mapToUChars) + 1;
56
+        // Note that toUCharsMapStart can be negative. Happens when the remaining
57
+        // text from current position to the beginning is less than the buffer size.
58
+        // + 1 because mapToUChars must have a slot at the end for the bufNativeLimit entry.
59
         int32_t  destIx = UTF8_TEXT_CHUNK_SIZE+2;   // Start in the overflow region
60
                                                     //   at end of buffer to leave room
61
                                                     //   for a surrogate pair at the
62
@@ -1338,6 +1352,7 @@ fillReverse:
63
             if (c<0x80) {
64
                 // Special case ASCII range for speed.
65
                 buf[destIx] = (UChar)c;
66
+                U_ASSERT(toUCharsMapStart <= srcIx);
67
                 mapToUChars[srcIx - toUCharsMapStart] = (uint8_t)destIx;
68
                 mapToNative[destIx] = (uint8_t)(srcIx - toUCharsMapStart);
69
             } else {
70
@@ -1367,6 +1382,7 @@ fillReverse:
71
                 do {
72
                     mapToUChars[sIx-- - toUCharsMapStart] = (uint8_t)destIx;
73
                 } while (sIx >= srcIx);
74
+                U_ASSERT(toUCharsMapStart <= (srcIx+1));
75
 
76
                 // Set native indexing limit to be the current position.
77
                 //   We are processing a non-ascii, non-native-indexing char now;
78
@@ -1541,6 +1557,7 @@ utf8TextMapIndexToUTF16(const UText *ut,
79
     U_ASSERT(index>=ut->chunkNativeStart+ut->nativeIndexingLimit);
80
     U_ASSERT(index<=ut->chunkNativeLimit);
81
     int32_t mapIndex = index - u8b->toUCharsMapStart;
82
+    U_ASSERT(mapIndex < (int32_t)sizeof(UTF8Buf::mapToUChars));
83
     int32_t offset = u8b->mapToUChars[mapIndex] - u8b->bufStartIdx;
84
     U_ASSERT(offset>=0 && offset<=ut->chunkLength);
85
     return offset;
86
--- test/intltest/utxttest.cpp.orig	2016-06-15 18:58:17 UTC
87
+++ test/intltest/utxttest.cpp
88
@@ -67,6 +67,8 @@ UTextTest::runIndexedTest(int32_t index,
89
             if (exec) Ticket10983();  break;
90
         case 7: name = "Ticket12130";
91
             if (exec) Ticket12130(); break;
92
+        case 8: name = "Ticket12888";
93
+            if (exec) Ticket12888(); break;
94
         default: name = "";          break;
95
     }
96
 }
97
@@ -1583,3 +1585,63 @@ void UTextTest::Ticket12130() {
98
     }
99
     utext_close(&ut);
100
 }
101
+
102
+// Ticket 12888: bad handling of illegal utf-8 containing many instances of the archaic, now illegal,
103
+//               six byte utf-8 forms. Original implementation had an assumption that
104
+//               there would be at most three utf-8 bytes per UTF-16 code unit.
105
+//               The five and six byte sequences map to a single replacement character.
106
+
107
+void UTextTest::Ticket12888() {
108
+    const char *badString =
109
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
110
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
111
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
112
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
113
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
114
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
115
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
116
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
117
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
118
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
119
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
120
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
121
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
122
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
123
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
124
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
125
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
126
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
127
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80"
128
+            "\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80\xfd\x80\x80\x80\x80\x80";
129
+
130
+    UErrorCode status = U_ZERO_ERROR;
131
+    LocalUTextPointer ut(utext_openUTF8(NULL, badString, -1, &status));
132
+    TEST_SUCCESS(status);
133
+    for (;;) {
134
+        UChar32 c = utext_next32(ut.getAlias());
135
+        if (c == U_SENTINEL) {
136
+            break;
137
+        }
138
+    }
139
+    int32_t endIdx = utext_getNativeIndex(ut.getAlias());
140
+    if (endIdx != (int32_t)strlen(badString)) {
141
+        errln("%s:%d expected=%d, actual=%d", __FILE__, __LINE__, strlen(badString), endIdx);
142
+        return;
143
+    }
144
+
145
+    for (int32_t prevIndex = endIdx; prevIndex>0;) {
146
+        UChar32 c = utext_previous32(ut.getAlias());
147
+        int32_t currentIndex = utext_getNativeIndex(ut.getAlias());
148
+        if (c != 0xfffd) {
149
+            errln("%s:%d (expected, actual, index) = (%d, %d, %d)\n",
150
+                    __FILE__, __LINE__, 0xfffd, c, currentIndex);
151
+            break;
152
+        }
153
+        if (currentIndex != prevIndex - 6) {
154
+            errln("%s:%d: wrong index. Expected, actual = %d, %d",
155
+                    __FILE__, __LINE__, prevIndex - 6, currentIndex);
156
+            break;
157
+        }
158
+        prevIndex = currentIndex;
159
+    }
160
+}
161
--- test/intltest/utxttest.h.orig	2016-06-15 18:58:17 UTC
162
+++ test/intltest/utxttest.h
163
@@ -38,6 +38,7 @@ public:
164
     void Ticket10562();
165
     void Ticket10983();
166
     void Ticket12130();
167
+    void Ticket12888();
168
 
169
 private:
170
     struct m {                              // Map between native indices & code points.

Return to bug 218788