@@ -2273,6 +2273,50 @@ static void s_iconv_close(uptr cd) {
2273
2273
ICONV_CLOSE ((iconv_t )cd );
2274
2274
}
2275
2275
2276
+ #ifdef DISTRUST_ICONV_PROGRESS
2277
+ # define ICONV_FROM iconv_fixup
2278
+ static size_t iconv_fixup (iconv_t cd , char * * src , size_t * srcleft , char * * dst , size_t * dstleft ) {
2279
+ size_t r ;
2280
+ char * orig_src = * src , * orig_dst = * dst ;
2281
+ size_t orig_srcleft = * srcleft , orig_dstleft = * dstleft , srcuntried = 0 ;
2282
+
2283
+ while (1 ) {
2284
+ r = iconv ((iconv_t )cd , src , srcleft , dst , dstleft );
2285
+ if ((r == (size_t )-1 )
2286
+ && (errno == E2BIG )
2287
+ && ((* srcleft < orig_srcleft ) || (* dstleft < orig_dstleft ))) {
2288
+ /* Avoid a macOS (as of 14.2.1 and 14.3.1) iconv bug in this
2289
+ case, where we don't trust that consumed input characters are
2290
+ reflected in the output pointer. Reverting progress should be
2291
+ ok for a correct iconv, too, since a -1 result means that no
2292
+ irreversible progress was made. */
2293
+ * src = orig_src ;
2294
+ * dst = orig_dst ;
2295
+ * srcleft = orig_srcleft ;
2296
+ * dstleft = orig_dstleft ;
2297
+
2298
+ /* We need to make progress, if possible, to satify normal iconv
2299
+ behavior and "io.ss" expectations. Try converting fewer
2300
+ characters. */
2301
+ if (orig_srcleft > sizeof (string_char )) {
2302
+ size_t try_chars = (orig_srcleft / sizeof (string_char )) / 2 ;
2303
+ srcuntried += orig_srcleft - (try_chars * sizeof (string_char ));
2304
+ orig_srcleft = try_chars * sizeof (string_char );
2305
+ * srcleft = orig_srcleft ;
2306
+ } else
2307
+ break ;
2308
+ } else
2309
+ break ;
2310
+ }
2311
+
2312
+ * srcleft += srcuntried ;
2313
+
2314
+ return r ;
2315
+ }
2316
+ #else
2317
+ # define ICONV_FROM ICONV
2318
+ #endif
2319
+
2276
2320
#define ICONV_BUFSIZ 400
2277
2321
2278
2322
static ptr s_iconv_from_string (uptr cd , ptr in , uptr i , uptr iend , ptr out , uptr o , uptr oend ) {
@@ -2298,7 +2342,8 @@ static ptr s_iconv_from_string(uptr cd, ptr in, uptr i, uptr iend, ptr out, uptr
2298
2342
under Windows, the iconv dll might have been linked against a different C runtime
2299
2343
and might therefore set a different errno */
2300
2344
errno = 0 ;
2301
- ICONV ((iconv_t )cd , (ICONV_INBUF_TYPE )& inbuf , & inbytesleft , & outbuf , & outbytesleft );
2345
+ ICONV_FROM ((iconv_t )cd , (ICONV_INBUF_TYPE )& inbuf , & inbytesleft , & outbuf , & outbytesleft );
2346
+
2302
2347
new_i = i + inmax - inbytesleft / sizeof (string_char );
2303
2348
new_o = oend - outbytesleft ;
2304
2349
if (new_i != i || new_o != o ) return Scons (Sinteger (new_i ), Sinteger (new_o ));
0 commit comments