Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adjustment and workaround for macOS iconv #805

Merged
merged 2 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ jobs:
os: macos-12
- machine: ta6osx
os: macos-12
- machine: arm64osx
os: macos-14
- machine: tarm64osx
os: macos-14
- machine: i3le
os: ubuntu-22.04
- machine: ti3le
Expand Down
47 changes: 46 additions & 1 deletion c/prim5.c
Original file line number Diff line number Diff line change
Expand Up @@ -2273,6 +2273,50 @@ static void s_iconv_close(uptr cd) {
ICONV_CLOSE((iconv_t)cd);
}

#ifdef DISTRUST_ICONV_PROGRESS
# define ICONV_FROM iconv_fixup
static size_t iconv_fixup(iconv_t cd, char **src, size_t *srcleft, char **dst, size_t *dstleft) {
size_t r;
char *orig_src = *src, *orig_dst = *dst;
size_t orig_srcleft = *srcleft, orig_dstleft = *dstleft, srcuntried = 0;

while (1) {
r = iconv((iconv_t)cd, src, srcleft, dst, dstleft);
if ((r == (size_t)-1)
&& (errno == E2BIG)
&& ((*srcleft < orig_srcleft) || (*dstleft < orig_dstleft))) {
/* Avoid a macOS (as of 14.2.1 and 14.3.1) iconv bug in this
case, where we don't trust that consumed input characters are
reflected in the output pointer. Reverting progress should be
ok for a correct iconv, too, since a -1 result means that no
irreversible progress was made. */
*src = orig_src;
*dst = orig_dst;
*srcleft = orig_srcleft;
*dstleft = orig_dstleft;

/* We need to make progress, if possible, to satify normal iconv
behavior and "io.ss" expectations. Try converting fewer
characters. */
if (orig_srcleft > sizeof(string_char)) {
size_t try_chars = (orig_srcleft / sizeof(string_char)) / 2;
srcuntried += orig_srcleft - (try_chars * sizeof(string_char));
orig_srcleft = try_chars * sizeof(string_char);
*srcleft = orig_srcleft;
} else
break;
} else
break;
}

*srcleft += srcuntried;

return r;
}
#else
# define ICONV_FROM ICONV
#endif

#define ICONV_BUFSIZ 400

static ptr s_iconv_from_string(uptr cd, ptr in, uptr i, uptr iend, ptr out, uptr o, uptr oend) {
Expand All @@ -2298,7 +2342,8 @@ static ptr s_iconv_from_string(uptr cd, ptr in, uptr i, uptr iend, ptr out, uptr
under Windows, the iconv dll might have been linked against a different C runtime
and might therefore set a different errno */
errno = 0;
ICONV((iconv_t)cd, (ICONV_INBUF_TYPE)&inbuf, &inbytesleft, &outbuf, &outbytesleft);
ICONV_FROM((iconv_t)cd, (ICONV_INBUF_TYPE)&inbuf, &inbytesleft, &outbuf, &outbytesleft);

new_i = i + inmax - inbytesleft / sizeof(string_char);
new_o = oend - outbytesleft;
if (new_i != i || new_o != o) return Scons(Sinteger(new_i), Sinteger(new_o));
Expand Down
2 changes: 2 additions & 0 deletions c/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ typedef int tputsputcchar;
#define NSECCTIME(sb) (sb).st_ctimespec.tv_nsec
#define NSECMTIME(sb) (sb).st_mtimespec.tv_nsec
#define ICONV_INBUF_TYPE char **
/* workaround issue in macOS 14.2.1 iconv: */
#define DISTRUST_ICONV_PROGRESS
#endif

#if defined(__QNX__)
Expand Down
8 changes: 6 additions & 2 deletions mats/io.ms
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,9 @@
'()
(if (fx= i #xD800)
(f #xE000)
(cons i (f (fx+ i 1)))))))
(if (fx= i #xFEFF) ; avoid BOM, which an encoder is arguably justified in dropping
(f (fx+ i 1))
(cons i (f (fx+ i 1))))))))
(define ls2
(let f ([n 1000000])
(if (fx= n 0)
Expand All @@ -1021,7 +1023,9 @@
(let ([n (random (- #x110000 (- #xE000 #xD800)))])
(if (<= #xD800 n #xDFFF)
(+ n (- #xE000 #xD800))
n))
(if (fx= n #xFEFF) ; avoid BOM
#xFEFE
n)))
(f (fx- n 1))))))
(define s (apply string (map integer->char (append ls1 ls2))))
#;(define s (apply string (map integer->char ls1)))
Expand Down