Observed behavior: $ echo -en "echo \${_//}" | ./busybox hush & [1] 1000 $ jobs [1]+ Running echo -en "echo \${_//}" | ./busybox hush & Expected behavior: $ echo -en "echo \${_//}" | ./busybox hush & [1] 1000 ./busybox [1]+ Done echo -en "echo \${_//}" | ./busybox hush When, instead of leaving it empty, a pattern that does not match is provided, the command works as expected. We found this behavior in version 1.27.2 and can also reproduce it with busybox 1.28.0 as well as the current master (commit d8fd88a09) compiled with make defconfig && make. The function that is called to compute the location of any matches, strstr_pattern() in hush.c, has the following behavior on an empty pattern: It computes the size of the match, which is 0, and returns the pointer given to it as start of the input. This return value is checked by replace_pattern(): while (1) { int size; char *s = strstr_pattern(val, pattern, &size); if (!s) break; // ... val = s + size; // ... } As the return value is not NULL (it points to the same address as val), the loop is not broken. As the size is zero, the pointer is not advanced, thus provoking the same behavior of strstr_pattern() as before. This behavior was found using Symbolic Execution techniques developed in the course of the SYMBIOSYS research project at COMSYS, RWTH Aachen University. This research is supported by the European Research Council (ERC) under the EU's Horizon 2020 Research and Innovation Programme grant agreement n. 647295 (SYMBIOSYS).
Fixed in git, thanks!