Skip to content

Commit 64cf30a

Browse files
authored
adjustment and workaround for macOS iconv (#805)
* work around issues with macOS iconv library * add arm64osx to CI Closes #797
1 parent ee20bd2 commit 64cf30a

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ jobs:
1515
os: macos-12
1616
- machine: ta6osx
1717
os: macos-12
18+
- machine: arm64osx
19+
os: macos-14
20+
- machine: tarm64osx
21+
os: macos-14
1822
- machine: i3le
1923
os: ubuntu-22.04
2024
- machine: ti3le

c/prim5.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2273,6 +2273,50 @@ static void s_iconv_close(uptr cd) {
22732273
ICONV_CLOSE((iconv_t)cd);
22742274
}
22752275

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+
22762320
#define ICONV_BUFSIZ 400
22772321

22782322
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
22982342
under Windows, the iconv dll might have been linked against a different C runtime
22992343
and might therefore set a different errno */
23002344
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+
23022347
new_i = i + inmax - inbytesleft / sizeof(string_char);
23032348
new_o = oend - outbytesleft;
23042349
if (new_i != i || new_o != o) return Scons(Sinteger(new_i), Sinteger(new_o));

c/version.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,8 @@ typedef int tputsputcchar;
328328
#define NSECCTIME(sb) (sb).st_ctimespec.tv_nsec
329329
#define NSECMTIME(sb) (sb).st_mtimespec.tv_nsec
330330
#define ICONV_INBUF_TYPE char **
331+
/* workaround issue in macOS 14.2.1 iconv: */
332+
#define DISTRUST_ICONV_PROGRESS
331333
#endif
332334

333335
#if defined(__QNX__)

mats/io.ms

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,9 @@
10121012
'()
10131013
(if (fx= i #xD800)
10141014
(f #xE000)
1015-
(cons i (f (fx+ i 1)))))))
1015+
(if (fx= i #xFEFF) ; avoid BOM, which an encoder is arguably justified in dropping
1016+
(f (fx+ i 1))
1017+
(cons i (f (fx+ i 1))))))))
10161018
(define ls2
10171019
(let f ([n 1000000])
10181020
(if (fx= n 0)
@@ -1021,7 +1023,9 @@
10211023
(let ([n (random (- #x110000 (- #xE000 #xD800)))])
10221024
(if (<= #xD800 n #xDFFF)
10231025
(+ n (- #xE000 #xD800))
1024-
n))
1026+
(if (fx= n #xFEFF) ; avoid BOM
1027+
#xFEFE
1028+
n)))
10251029
(f (fx- n 1))))))
10261030
(define s (apply string (map integer->char (append ls1 ls2))))
10271031
#;(define s (apply string (map integer->char ls1)))

0 commit comments

Comments
 (0)