From 4856d5580b5ba83624e991d0b4f69201279a5d38 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 20 Feb 2024 11:13:46 -0800 Subject: [PATCH] Avoid malloc dependency in tzset (#21375) --- src/generated_struct_info32.json | 1 + src/generated_struct_info64.json | 1 + src/library.js | 23 ++++++++++++----------- src/library_sigs.js | 2 +- src/struct_info.json | 6 ++++++ system/lib/libc/emscripten_internal.h | 2 +- system/lib/libc/tzset.c | 8 +++++++- test/test_other.py | 2 +- 8 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/generated_struct_info32.json b/src/generated_struct_info32.json index 845bdd7a9faa..14e1132df998 100644 --- a/src/generated_struct_info32.json +++ b/src/generated_struct_info32.json @@ -401,6 +401,7 @@ "TIOCGWINSZ": 21523, "TIOCSPGRP": 21520, "TIOCSWINSZ": 21524, + "TZNAME_MAX": 6, "UUID_TYPE_DCE_RANDOM": 4, "UUID_VARIANT_DCE": 1, "W_OK": 2, diff --git a/src/generated_struct_info64.json b/src/generated_struct_info64.json index d73629077534..e6e6f133a358 100644 --- a/src/generated_struct_info64.json +++ b/src/generated_struct_info64.json @@ -401,6 +401,7 @@ "TIOCGWINSZ": 21523, "TIOCSPGRP": 21520, "TIOCSWINSZ": 21524, + "TZNAME_MAX": 6, "UUID_TYPE_DCE_RANDOM": 4, "UUID_VARIANT_DCE": 1, "W_OK": 2, diff --git a/src/library.js b/src/library.js index b30e852d6600..dab6accfb5a4 100644 --- a/src/library.js +++ b/src/library.js @@ -604,9 +604,9 @@ addToLibrary({ return ret; }, - _tzset_js__deps: ['$stringToNewUTF8'], + _tzset_js__deps: ['$stringToUTF8'], _tzset_js__internal: true, - _tzset_js: (timezone, daylight, tzname) => { + _tzset_js: (timezone, daylight, std_name, dst_name) => { // TODO: Use (malleable) environment variables instead of system settings. var currentYear = new Date().getFullYear(); var winter = new Date(currentYear, 0, 1); @@ -614,9 +614,12 @@ addToLibrary({ var winterOffset = winter.getTimezoneOffset(); var summerOffset = summer.getTimezoneOffset(); - // Local standard timezone offset. Local standard time is not adjusted for daylight savings. - // This code uses the fact that getTimezoneOffset returns a greater value during Standard Time versus Daylight Saving Time (DST). - // Thus it determines the expected output during Standard Time, and it compares whether the output of the given date the same (Standard) or less (DST). + // Local standard timezone offset. Local standard time is not adjusted for + // daylight savings. This code uses the fact that getTimezoneOffset returns + // a greater value during Standard Time versus Daylight Saving Time (DST). + // Thus it determines the expected output during Standard Time, and it + // compares whether the output of the given date the same (Standard) or less + // (DST). var stdTimezoneOffset = Math.max(winterOffset, summerOffset); // timezone is specified as seconds west of UTC ("The external variable @@ -634,15 +637,13 @@ addToLibrary({ }; var winterName = extractZone(winter); var summerName = extractZone(summer); - var winterNamePtr = stringToNewUTF8(winterName); - var summerNamePtr = stringToNewUTF8(summerName); if (summerOffset < winterOffset) { // Northern hemisphere - {{{ makeSetValue('tzname', '0', 'winterNamePtr', POINTER_TYPE) }}}; - {{{ makeSetValue('tzname', POINTER_SIZE, 'summerNamePtr', POINTER_TYPE) }}}; + stringToUTF8(winterName, std_name, {{{ cDefs.TZNAME_MAX + 1 }}}); + stringToUTF8(summerName, dst_name, {{{ cDefs.TZNAME_MAX + 1 }}}); } else { - {{{ makeSetValue('tzname', '0', 'summerNamePtr', POINTER_TYPE) }}}; - {{{ makeSetValue('tzname', POINTER_SIZE, 'winterNamePtr', POINTER_TYPE) }}}; + stringToUTF8(winterName, dst_name, {{{ cDefs.TZNAME_MAX + 1 }}}); + stringToUTF8(summerName, std_name, {{{ cDefs.TZNAME_MAX + 1 }}}); } }, diff --git a/src/library_sigs.js b/src/library_sigs.js index bd173e74558f..d63cd503c6bd 100644 --- a/src/library_sigs.js +++ b/src/library_sigs.js @@ -382,7 +382,7 @@ sigs = { _munmap_js__sig: 'ippiiij', _setitimer_js__sig: 'iid', _timegm_js__sig: 'jp', - _tzset_js__sig: 'vppp', + _tzset_js__sig: 'vpppp', _wasmfs_copy_preloaded_file_data__sig: 'vip', _wasmfs_create_fetch_backend_js__sig: 'vp', _wasmfs_create_js_file_backend_js__sig: 'vp', diff --git a/src/struct_info.json b/src/struct_info.json index 9358ded0a8db..5262b797e93e 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -318,6 +318,12 @@ "X_OK" ] }, + { + "file": "limits.h", + "defines": [ + "TZNAME_MAX" + ] + }, { "file": "bits/errno.h", "defines": [ diff --git a/system/lib/libc/emscripten_internal.h b/system/lib/libc/emscripten_internal.h index afcf1df87ce9..186b1582cfe0 100644 --- a/system/lib/libc/emscripten_internal.h +++ b/system/lib/libc/emscripten_internal.h @@ -44,7 +44,7 @@ time_t _mktime_js(struct tm* tm); void _localtime_js(time_t t, struct tm* __restrict__ tm); void _gmtime_js(time_t t, struct tm* __restrict__ tm); -void _tzset_js(long* timezone, int* daylight, char** tzname); +void _tzset_js(long* timezone, int* daylight, char* std_name, char* dst_name); const char* emscripten_pc_get_function(uintptr_t pc); const char* emscripten_pc_get_file(uintptr_t pc); diff --git a/system/lib/libc/tzset.c b/system/lib/libc/tzset.c index bdc580fcd029..1c6257aa45b9 100644 --- a/system/lib/libc/tzset.c +++ b/system/lib/libc/tzset.c @@ -4,19 +4,25 @@ * University of Illinois/NCSA Open Source License. Both these licenses can be * found in the LICENSE file. */ +#include #include #include #include #include "emscripten_internal.h" +static char std_name[TZNAME_MAX+1]; +static char dst_name[TZNAME_MAX+1]; + weak void tzset() { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static _Atomic bool done_init = false; if (!done_init) { pthread_mutex_lock(&lock); if (!done_init) { - _tzset_js(&timezone, &daylight, tzname); + _tzset_js(&timezone, &daylight, std_name, dst_name); + tzname[0] = std_name; + tzname[1] = dst_name; done_init = true; } pthread_mutex_unlock(&lock); diff --git a/test/test_other.py b/test/test_other.py index 6977575295fd..eb10b3872d27 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -5663,7 +5663,7 @@ def test_only_force_stdlibs(self, env, fail): with env_modify(env): if fail: err = self.expect_fail(cmd) - self.assertContained('undefined symbol: malloc', err) + self.assertContained('undefined symbol: emscripten_builtin_memalign', err) else: err = self.run_process(cmd, stderr=PIPE).stderr if 'EMCC_ONLY_FORCED_STDLIBS' in env: