on master help sign in
Improve on previous fix

This version tries to force the real decoding function to be inlined into each of its callers, which in turn each have different criteria for backing up a byte. This avoids an extra test at the end of strict decoding. While this seems to fix gh-61, I want to beef up the test suite so that it will correctly detect the bug.

commit7c09f3c5d09b9e031a1124bdddf15b18f27efe84 authorBryan O'Sullivan <bos@serpentine.com> dateSun 29 Dec 2013, 23:12 (13 years ago) parente7c230b
1 file changed+29−12
cbits/cbits.c+29−12
cbits/cbits.c+29−12
@@ -123,10 +123,18 @@ _hs_text_decode_latin1(uint16_t *dest, const uint8_t const *src,
123123 * state0 != UTF8_ACCEPT, UTF8_REJECT
124124 *
125125 */
126−uint8_t const *
127−_hs_text_decode_utf8_state(uint16_t *dest, size_t *destoff,
128− const uint8_t const *src, const uint8_t const *srcend,
129− uint32_t *codepoint0, uint32_t *state0)
126+
127+#if defined(__GNUC__) || defined(__clang__)
128+static inline uint8_t const *
129+_hs_text_decode_utf8_int(uint16_t *dest, size_t *destoff,
130+ const uint8_t const *src, const uint8_t const *srcend,
131+ uint32_t *codepoint0, uint32_t *state0)
132+ __attribute((always_inline));
133+#endif
134+static inline uint8_t const *
135+_hs_text_decode_utf8_int(uint16_t *dest, size_t *destoff,
136+ const uint8_t const *src, const uint8_t const *srcend,
137+ uint32_t *codepoint0, uint32_t *state0)
130138{
131139 uint16_t *d = dest + *destoff;
132140 const uint8_t const *s = src;
@@ -178,10 +186,6 @@ _hs_text_decode_utf8_state(uint16_t *dest, size_t *destoff,
178186 }
179187 }
180188
181− /* Invalid encoding, back up to the errant character */
182− if (state == UTF8_REJECT)
183− s -= 1;
184−
185189 *destoff = d - dest;
186190 *codepoint0 = codepoint;
187191 *state0 = state;
@@ -189,6 +193,19 @@ _hs_text_decode_utf8_state(uint16_t *dest, size_t *destoff,
189193 return s;
190194}
191195
196+uint8_t const *
197+_hs_text_decode_utf8_state(uint16_t *dest, size_t *destoff,
198+ const uint8_t const *src,
199+ const uint8_t const *srcend,
200+ uint32_t *codepoint0, uint32_t *state0)
201+{
202+ uint8_t const *ret = _hs_text_decode_utf8_int(dest, destoff, src, srcend,
203+ codepoint0, state0);
204+ if (*state0 == UTF8_REJECT)
205+ ret -=1;
206+ return ret;
207+}
208+
192209/*
193210 * Helper to decode buffer and discard final decoder state
194211 */
@@ -198,10 +215,10 @@ _hs_text_decode_utf8(uint16_t *dest, size_t *destoff,
198215{
199216 uint32_t codepoint;
200217 uint32_t state = UTF8_ACCEPT;
201− uint8_t const *ret = _hs_text_decode_utf8_state(dest, destoff, src, srcend,
202− &codepoint, &state);
203− /* Back up if we have an incomplete encoding */
204− if (state != UTF8_ACCEPT && state != UTF8_REJECT)
218+ uint8_t const *ret = _hs_text_decode_utf8_int(dest, destoff, src, srcend,
219+ &codepoint, &state);
220+ /* Back up if we have an incomplete or invalid encoding */
221+ if (state != UTF8_ACCEPT)
205222 ret -= 1;
206223 return ret;
207224}