From a6cc74255abfbc530ecc590ab84cd15dcf956bd4 Mon Sep 17 00:00:00 2001 From: google-yfyang Date: Mon, 10 Nov 2025 12:52:00 -0500 Subject: [PATCH 1/3] Add error handling for stderrno when errno is invalid --- system/lib/libc/musl/src/errno/__strerror.h | 4 +++- system/lib/libc/musl/src/errno/strerror.c | 10 ++++++++-- test/test_core.py | 4 ++++ test/unistd/errno.c | 17 +++++++++++++++++ test/unistd/errno.out | 1 + 5 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 test/unistd/errno.c create mode 100644 test/unistd/errno.out diff --git a/system/lib/libc/musl/src/errno/__strerror.h b/system/lib/libc/musl/src/errno/__strerror.h index 47d56a15db108..598af448c5102 100644 --- a/system/lib/libc/musl/src/errno/__strerror.h +++ b/system/lib/libc/musl/src/errno/__strerror.h @@ -3,7 +3,9 @@ * with these messages, and then to define a lookup table translating * error codes to offsets of corresponding fields in the structure. */ #if defined(__EMSCRIPTEN__) -// This is intended to match the errno in llvm-libc. +/* Error handling is introduced to match the behavior in llvm-libc. + * When invalid errno is specified, Unknown error: errno_code is emitted. + */ E(0, "Success") #else E(0, "No error information") diff --git a/system/lib/libc/musl/src/errno/strerror.c b/system/lib/libc/musl/src/errno/strerror.c index 8ee4ac2f8b9ee..4126f58eb84ef 100644 --- a/system/lib/libc/musl/src/errno/strerror.c +++ b/system/lib/libc/musl/src/errno/strerror.c @@ -34,15 +34,21 @@ char *__strerror_l(int e, locale_t loc) if (e==EDQUOT) e=0; else if (e==EDQUOT_ORIG) e=EDQUOT; #endif - if (e >= sizeof errmsgidx / sizeof *errmsgidx) e = 0; - s = (char *)&errmsgstr + errmsgidx[e]; #ifdef __EMSCRIPTEN__ + if (e < 0 || e >= sizeof errmsgidx / sizeof *errmsgidx || (e != 0 && !errmsgidx[e])) { + static char buf[32]; + snprintf(buf, sizeof buf, "Unknown error %d", e); + return buf; + } + s = (char *)&errmsgstr + errmsgidx[e]; // strerror is a (debug) dependency of many emscripten syscalls which mean it // must be excluded from LTO, along with all of its dependencies. // In order to limit the transitive dependencies we disable localization of // rrno messages here. return (char *)s; #else + if (e >= sizeof errmsgidx / sizeof *errmsgidx) e = 0; + s = (char *)&errmsgstr + errmsgidx[e]; return (char *)LCTRANS(s, LC_MESSAGES, loc); #endif } diff --git a/test/test_core.py b/test/test_core.py index eb03a3aac0305..aa9ba9baa707f 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -6169,6 +6169,10 @@ def test_unistd_curdir(self): def test_unistd_close(self): self.do_run_in_out_file_test('unistd/close.c') + @also_with_noderawfs + def test_unistd_errno(self): + self.do_run_in_out_file_test('unistd/errno.c') + def test_unistd_fsync_stdout(self): self.do_run_in_out_file_test('unistd/fsync_stdout.c') diff --git a/test/unistd/errno.c b/test/unistd/errno.c new file mode 100644 index 0000000000000..9663824188bbe --- /dev/null +++ b/test/unistd/errno.c @@ -0,0 +1,17 @@ +/* + * Copyright 2011 The Emscripten Authors. All rights reserved. + * Emscripten is available under two separate licenses, the MIT license and the + * University of Illinois/NCSA Open Source License. Both these licenses can be + * found in the LICENSE file. + */ + +#include +#include +#include +#include +#include + +int main() { + int error = -1; + printf("errno: %s\n", strerror(error)); +} \ No newline at end of file diff --git a/test/unistd/errno.out b/test/unistd/errno.out new file mode 100644 index 0000000000000..134e2af249f9f --- /dev/null +++ b/test/unistd/errno.out @@ -0,0 +1 @@ +errno: Unknown error -1 From 0631168c3900ad69c4de3f1b9bebb92d2e0f2d7a Mon Sep 17 00:00:00 2001 From: google-yfyang Date: Tue, 11 Nov 2025 11:48:34 -0500 Subject: [PATCH 2/3] remove the error code from the error message. --- system/lib/libc/musl/src/errno/strerror.c | 4 +--- test/test_core.py | 4 ---- test/test_other.py | 3 +++ test/unistd/errno.out | 1 - test/unistd/{errno.c => strerror.c} | 8 ++------ test/unistd/strerror.out | 1 + 6 files changed, 7 insertions(+), 14 deletions(-) delete mode 100644 test/unistd/errno.out rename test/unistd/{errno.c => strerror.c} (56%) create mode 100644 test/unistd/strerror.out diff --git a/system/lib/libc/musl/src/errno/strerror.c b/system/lib/libc/musl/src/errno/strerror.c index 4126f58eb84ef..0fd1c84289a2e 100644 --- a/system/lib/libc/musl/src/errno/strerror.c +++ b/system/lib/libc/musl/src/errno/strerror.c @@ -36,9 +36,7 @@ char *__strerror_l(int e, locale_t loc) #endif #ifdef __EMSCRIPTEN__ if (e < 0 || e >= sizeof errmsgidx / sizeof *errmsgidx || (e != 0 && !errmsgidx[e])) { - static char buf[32]; - snprintf(buf, sizeof buf, "Unknown error %d", e); - return buf; + return "Unknown error"; } s = (char *)&errmsgstr + errmsgidx[e]; // strerror is a (debug) dependency of many emscripten syscalls which mean it diff --git a/test/test_core.py b/test/test_core.py index aa9ba9baa707f..eb03a3aac0305 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -6169,10 +6169,6 @@ def test_unistd_curdir(self): def test_unistd_close(self): self.do_run_in_out_file_test('unistd/close.c') - @also_with_noderawfs - def test_unistd_errno(self): - self.do_run_in_out_file_test('unistd/errno.c') - def test_unistd_fsync_stdout(self): self.do_run_in_out_file_test('unistd/fsync_stdout.c') diff --git a/test/test_other.py b/test/test_other.py index a0fc309d2e0dc..b9f0392da0ce4 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -13124,6 +13124,9 @@ def test_wasmfs_before_preload(self): def test_hello_world_above_2gb(self): self.do_run_in_out_file_test('hello_world.c', cflags=['-sGLOBAL_BASE=2GB', '-sINITIAL_MEMORY=3GB']) + def test_unistd_strerror(self): + self.do_run_in_out_file_test('unistd/strerror.c') + def test_hello_function(self): # hello_function.cpp is referenced/used in the docs. This test ensures that it # at least compiles. diff --git a/test/unistd/errno.out b/test/unistd/errno.out deleted file mode 100644 index 134e2af249f9f..0000000000000 --- a/test/unistd/errno.out +++ /dev/null @@ -1 +0,0 @@ -errno: Unknown error -1 diff --git a/test/unistd/errno.c b/test/unistd/strerror.c similarity index 56% rename from test/unistd/errno.c rename to test/unistd/strerror.c index 9663824188bbe..6460dccf4cc94 100644 --- a/test/unistd/errno.c +++ b/test/unistd/strerror.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 The Emscripten Authors. All rights reserved. + * Copyright 2025 The Emscripten Authors. All rights reserved. * Emscripten is available under two separate licenses, the MIT license and the * University of Illinois/NCSA Open Source License. Both these licenses can be * found in the LICENSE file. @@ -7,11 +7,7 @@ #include #include -#include -#include -#include int main() { - int error = -1; - printf("errno: %s\n", strerror(error)); + printf("errno: %s\n", strerror(-1)); } \ No newline at end of file diff --git a/test/unistd/strerror.out b/test/unistd/strerror.out new file mode 100644 index 0000000000000..5e4ec470ac518 --- /dev/null +++ b/test/unistd/strerror.out @@ -0,0 +1 @@ +errno: Unknown error From 58bcbd74aee34da821023e88ccafd554375ad519 Mon Sep 17 00:00:00 2001 From: google-yfyang Date: Tue, 11 Nov 2025 14:16:07 -0500 Subject: [PATCH 3/3] code size updates --- test/codesize/test_codesize_cxx_except.json | 8 ++++---- test/codesize/test_codesize_cxx_except_wasm.json | 8 ++++---- .../test_codesize_cxx_except_wasm_legacy.json | 8 ++++---- test/codesize/test_codesize_cxx_mangle.json | 8 ++++---- test/codesize/test_codesize_hello_O0.json | 8 ++++---- test/codesize/test_codesize_hello_dylink_all.json | 4 ++-- test/codesize/test_unoptimized_code_size.json | 12 ++++++------ test/unistd/strerror.c | 2 +- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/test/codesize/test_codesize_cxx_except.json b/test/codesize/test_codesize_cxx_except.json index 0e7a4a8c28ad1..4dde3d8ee470a 100644 --- a/test/codesize/test_codesize_cxx_except.json +++ b/test/codesize/test_codesize_cxx_except.json @@ -1,10 +1,10 @@ { "a.out.js": 23325, "a.out.js.gz": 9128, - "a.out.nodebug.wasm": 171265, - "a.out.nodebug.wasm.gz": 57337, - "total": 194590, - "total_gz": 66465, + "a.out.nodebug.wasm": 171311, + "a.out.nodebug.wasm.gz": 57348, + "total": 194636, + "total_gz": 66476, "sent": [ "__cxa_begin_catch", "__cxa_end_catch", diff --git a/test/codesize/test_codesize_cxx_except_wasm.json b/test/codesize/test_codesize_cxx_except_wasm.json index 2cfcaaef41f42..12f821fb72467 100644 --- a/test/codesize/test_codesize_cxx_except_wasm.json +++ b/test/codesize/test_codesize_cxx_except_wasm.json @@ -1,10 +1,10 @@ { "a.out.js": 19486, "a.out.js.gz": 8077, - "a.out.nodebug.wasm": 144620, - "a.out.nodebug.wasm.gz": 54891, - "total": 164106, - "total_gz": 62968, + "a.out.nodebug.wasm": 144667, + "a.out.nodebug.wasm.gz": 54907, + "total": 164153, + "total_gz": 62984, "sent": [ "_abort_js", "_tzset_js", diff --git a/test/codesize/test_codesize_cxx_except_wasm_legacy.json b/test/codesize/test_codesize_cxx_except_wasm_legacy.json index 863e379ebfe32..89914a35b80ab 100644 --- a/test/codesize/test_codesize_cxx_except_wasm_legacy.json +++ b/test/codesize/test_codesize_cxx_except_wasm_legacy.json @@ -1,10 +1,10 @@ { "a.out.js": 19555, "a.out.js.gz": 8099, - "a.out.nodebug.wasm": 142209, - "a.out.nodebug.wasm.gz": 54350, - "total": 161764, - "total_gz": 62449, + "a.out.nodebug.wasm": 142256, + "a.out.nodebug.wasm.gz": 54366, + "total": 161811, + "total_gz": 62465, "sent": [ "_abort_js", "_tzset_js", diff --git a/test/codesize/test_codesize_cxx_mangle.json b/test/codesize/test_codesize_cxx_mangle.json index b1ccfb1c4ef27..2b7f4d6cee050 100644 --- a/test/codesize/test_codesize_cxx_mangle.json +++ b/test/codesize/test_codesize_cxx_mangle.json @@ -1,10 +1,10 @@ { "a.out.js": 23375, "a.out.js.gz": 9148, - "a.out.nodebug.wasm": 235299, - "a.out.nodebug.wasm.gz": 78928, - "total": 258674, - "total_gz": 88076, + "a.out.nodebug.wasm": 235343, + "a.out.nodebug.wasm.gz": 78952, + "total": 258718, + "total_gz": 88100, "sent": [ "__cxa_begin_catch", "__cxa_end_catch", diff --git a/test/codesize/test_codesize_hello_O0.json b/test/codesize/test_codesize_hello_O0.json index e6497a8e4b083..80b4283b27a31 100644 --- a/test/codesize/test_codesize_hello_O0.json +++ b/test/codesize/test_codesize_hello_O0.json @@ -1,10 +1,10 @@ { "a.out.js": 24194, "a.out.js.gz": 8694, - "a.out.nodebug.wasm": 15117, - "a.out.nodebug.wasm.gz": 7456, - "total": 39311, - "total_gz": 16150, + "a.out.nodebug.wasm": 15168, + "a.out.nodebug.wasm.gz": 7488, + "total": 39362, + "total_gz": 16182, "sent": [ "fd_write" ], diff --git a/test/codesize/test_codesize_hello_dylink_all.json b/test/codesize/test_codesize_hello_dylink_all.json index b37ea4b14f69c..37009f94946f8 100644 --- a/test/codesize/test_codesize_hello_dylink_all.json +++ b/test/codesize/test_codesize_hello_dylink_all.json @@ -1,7 +1,7 @@ { "a.out.js": 245483, - "a.out.nodebug.wasm": 574056, - "total": 819539, + "a.out.nodebug.wasm": 573907, + "total": 819390, "sent": [ "IMG_Init", "IMG_Load", diff --git a/test/codesize/test_unoptimized_code_size.json b/test/codesize/test_unoptimized_code_size.json index 6a8b4979da572..f885ffeb5f84f 100644 --- a/test/codesize/test_unoptimized_code_size.json +++ b/test/codesize/test_unoptimized_code_size.json @@ -1,16 +1,16 @@ { "hello_world.js": 56928, "hello_world.js.gz": 17700, - "hello_world.wasm": 15117, - "hello_world.wasm.gz": 7456, + "hello_world.wasm": 15168, + "hello_world.wasm.gz": 7488, "no_asserts.js": 26632, "no_asserts.js.gz": 8884, "no_asserts.wasm": 12217, "no_asserts.wasm.gz": 6015, "strict.js": 54943, "strict.js.gz": 17045, - "strict.wasm": 15117, - "strict.wasm.gz": 7451, - "total": 180954, - "total_gz": 64551 + "strict.wasm": 15168, + "strict.wasm.gz": 7482, + "total": 181056, + "total_gz": 64614 } diff --git a/test/unistd/strerror.c b/test/unistd/strerror.c index 6460dccf4cc94..8895773ec71d1 100644 --- a/test/unistd/strerror.c +++ b/test/unistd/strerror.c @@ -10,4 +10,4 @@ int main() { printf("errno: %s\n", strerror(-1)); -} \ No newline at end of file +}