-
- Notifications
You must be signed in to change notification settings - Fork 33.8k
Description
Version
18.9.0
Platform
Darwin
Subsystem
child_process
os
What steps will reproduce the bug?
In the current implementation, spawn and related functions throw synchronous errors for invalid signals, e.g.:
import { spawn } from 'node:child_process'; // TypeError [ERR_UNKNOWN_SIGNAL] spawn(process.execPath, ['-v'], { killSignal: 12345 });Anyway, it's easy to define custom signals that pass the validation:
import { spawn } from 'node:child_process'; import { constants } from 'node:os'; constants.signals.FOOBAR = 12345; // no error spawn(process.execPath, ['-v'], { killSignal: 12345 });The same applies when signals are identified by name, i.e:
import { spawn } from 'node:child_process'; // TypeError [ERR_UNKNOWN_SIGNAL] spawn(process.execPath, ['-v'], { killSignal: 'FOOBAR' });and
import { spawn } from 'node:child_process'; import { constants } from 'node:os'; constants.signals.FOOBAR = 12345; // no error spawn(process.execPath, ['-v'], { killSignal: 'FOOBAR' });but if a custom signal is added after the internal mapping of numeric codes to names signals has been generated, validation fails for numeric codes (but not for signal names):
import { spawn } from 'node:child_process'; import { constants } from 'node:os'; spawn(process.execPath, ['-v'], { killSignal: 1 }); constants.signals.FOOBAR = 12345; spawn(process.execPath, ['-v'], { killSignal: 'FOOBAR' }); // no error spawn(process.execPath, ['-v'], { killSignal: 12345 }); // TypeError [ERR_UNKNOWN_SIGNAL]This strikes to me as issue of improper memoization:
Lines 272 to 283 in 9ae2af4
| let signalsToNamesMapping; | |
| function getSignalsToNamesMapping() { | |
| if (signalsToNamesMapping !== undefined) | |
| return signalsToNamesMapping; | |
| signalsToNamesMapping = ObjectCreate(null); | |
| for (const key in signals) { | |
| signalsToNamesMapping[signals[key]] = key; | |
| } | |
| return signalsToNamesMapping; | |
| } |
where signalsToNamesMapping never changes once created.
On the other hand, I'm not convinced that the current behavior - being able to add, remove, and change signals at will - is intended. If it is, then the validation logic should be fixed. If it is not, then constants.signals should be better frozen to prevent changes.
How often does it reproduce? Is there a required condition?
All the time.
What is the expected behavior?
Either custom numeric signals should always be accepted as valid, or they should always be rejected. If they should be rejected, then custom string signals should be rejected, too.
What do you see instead?
Inconsistent behavior, depending on (possibly unrelated) previous operations.
Additional information
No response