Skip to content

Commit e9f070c

Browse files
authored
Add type checking for -s settings (#16539)
For almost all types there is single type that can be inferred from the default value. There are a few exceptions, where a single settings couple have more than one type (for example `PTHREAD_POOL_SIZE` can be an integer or string). For now, I simply exclude those few settings from the type checking. For now, I've not tried to add any extra annotations to the settings file. We could possibly followup by adding explicit annotations and/or support for polymorphic settings, but this change is big with with minimal impact. Fixes: #16440
1 parent 4c1d07d commit e9f070c

File tree

9 files changed

+259
-227
lines changed

9 files changed

+259
-227
lines changed

ChangeLog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ See docs/process.md for more on how version tagging works.
2020

2121
3.1.8
2222
-----
23+
- Command line settings (`-s`) are now type checked. For example, passing a
24+
string to a boolean setting will now generate an error (e.g.
25+
`-sEXIT_RUNTIME=foo`). Previously, the value of `foo` would have have been
26+
interpreted as non-zero and accepted as valid. (#16539)
2327
- A warning (limited-postlink-optimizations) was added that gets shown when
2428
binaryen optimizations are limited due to DWARF information being requested.
2529
Several binaryen passed are not compatible with the preservation of DWARF

emcc.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -376,25 +376,17 @@ def apply_settings(user_settings):
376376
else:
377377
value = value.replace('\\', '\\\\')
378378

379-
existing = getattr(settings, user_key, None)
380-
expect_list = type(existing) == list
379+
expected_type = settings.types.get(key)
381380

382-
if filename and expect_list and value.strip()[0] != '[':
381+
if filename and expected_type == list and value.strip()[0] != '[':
383382
# Prefer simpler one-line-per value parser
384383
value = parse_symbol_list_file(value)
385384
else:
386385
try:
387-
value = parse_value(value, expect_list)
386+
value = parse_value(value, expected_type)
388387
except Exception as e:
389388
exit_with_error('a problem occurred in evaluating the content after a "-s", specifically "%s=%s": %s', key, value, str(e))
390389

391-
# Do some basic type checking by comparing to the existing settings.
392-
# Sadly we can't do this generically in the SettingsManager since there are settings
393-
# that so change types internally over time.
394-
# We only currently worry about lists vs non-lists.
395-
if expect_list != (type(value) == list):
396-
exit_with_error('setting `%s` expects `%s` but got `%s`' % (user_key, type(existing), type(value)))
397-
398390
setattr(settings, user_key, value)
399391

400392
if key == 'EXPORTED_FUNCTIONS':
@@ -1808,7 +1800,7 @@ def phase_linker_setup(options, state, newargs, user_settings):
18081800
exit_with_error('--emrun is not compatible with MINIMAL_RUNTIME')
18091801

18101802
if options.use_closure_compiler:
1811-
settings.USE_CLOSURE_COMPILER = options.use_closure_compiler
1803+
settings.USE_CLOSURE_COMPILER = 1
18121804

18131805
if settings.CLOSURE_WARNINGS not in ['quiet', 'warn', 'error']:
18141806
exit_with_error('Invalid option -s CLOSURE_WARNINGS=%s specified! Allowed values are "quiet", "warn" or "error".' % settings.CLOSURE_WARNINGS)
@@ -3876,7 +3868,7 @@ def parse_symbol_list_file(contents):
38763868
return [v.strip() for v in values]
38773869

38783870

3879-
def parse_value(text, expect_list):
3871+
def parse_value(text, expected_type):
38803872
# Note that using response files can introduce whitespace, if the file
38813873
# has a newline at the end. For that reason, we rstrip() in relevant
38823874
# places here.
@@ -3931,14 +3923,20 @@ def parse_string_list(text):
39313923
return []
39323924
return parse_string_list_members(text)
39333925

3934-
if expect_list or (text and text[0] == '['):
3926+
if expected_type == list or (text and text[0] == '['):
39353927
# if json parsing fails, we fall back to our own parser, which can handle a few
39363928
# simpler syntaxes
39373929
try:
39383930
return json.loads(text)
39393931
except ValueError:
39403932
return parse_string_list(text)
39413933

3934+
if expected_type == float:
3935+
try:
3936+
return float(text)
3937+
except ValueError:
3938+
pass
3939+
39423940
try:
39433941
if text.startswith('0x'):
39443942
base = 16

emscripten.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,11 @@ def update_settings_glue(metadata):
136136
if settings.MEMORY64:
137137
assert '--enable-memory64' in settings.BINARYEN_FEATURES
138138

139-
settings.HAS_MAIN = settings.MAIN_MODULE or settings.STANDALONE_WASM or 'main' in settings.WASM_EXPORTS
139+
settings.HAS_MAIN = bool(settings.MAIN_MODULE) or settings.STANDALONE_WASM or 'main' in settings.WASM_EXPORTS
140140

141141
# When using dynamic linking the main function might be in a side module.
142142
# To be safe assume they do take input parametes.
143-
settings.MAIN_READS_PARAMS = metadata['mainReadsParams'] or settings.MAIN_MODULE
143+
settings.MAIN_READS_PARAMS = metadata['mainReadsParams'] or bool(settings.MAIN_MODULE)
144144

145145
if settings.STACK_OVERFLOW_CHECK and not settings.SIDE_MODULE:
146146
settings.EXPORTED_RUNTIME_METHODS += ['writeStackCookie', 'checkStackCookie']

src/library.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2568,7 +2568,7 @@ LibraryManager.library = {
25682568
name = UTF8ToString(name);
25692569

25702570
var ret = getCompilerSetting(name);
2571-
if (typeof ret == 'number') return ret;
2571+
if (typeof ret == 'number' || typeof ret == 'boolean') return ret;
25722572

25732573
if (!_emscripten_get_compiler_setting.cache) _emscripten_get_compiler_setting.cache = {};
25742574
var cache = _emscripten_get_compiler_setting.cache;

src/parseTools.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -918,11 +918,10 @@ function makeRetainedCompilerSettings() {
918918
const ret = {};
919919
for (const x in global) {
920920
if (!ignore.has(x) && x[0] !== '_' && x == x.toUpperCase()) {
921-
try {
922-
if (typeof global[x] == 'number' || typeof global[x] == 'string' || this.isArray()) {
923-
ret[x] = global[x];
924-
}
925-
} catch (e) {}
921+
const value = global[x];
922+
if (typeof value == 'number' || typeof value == 'boolean' || typeof value == 'string' || Array.isArray(x)) {
923+
ret[x] = value;
924+
}
926925
}
927926
}
928927
return ret;

0 commit comments

Comments
 (0)