Skip to content

Instantly share code, notes, and snippets.

@antichris
Created May 6, 2022 11:11
Show Gist options
  • Save antichris/c37e6362cbe10385a26d820f40c07a87 to your computer and use it in GitHub Desktop.
Save antichris/c37e6362cbe10385a26d820f40c07a87 to your computer and use it in GitHub Desktop.
Emitting binary from POSIX shell scripts

Emitting binary from POSIX shell scripts

Different (supposedly) POSIX compliant shell environments yield varied results when asked to emit non-printable characters. But there is one method that works consistently across a wide variety of shells.

Sparked by this conversation.

Comparison

Given

hex='\x40\x00\x40'
hex2='\\x40\\x00\\x40'
oct='\100\000\100'
oct2='\0100\0000\0100'

you get this:

dashᵃ dashᵇ ksh bash BusyBox sh zsh
echo -n "$hex" $hex¹ $hex $hex $hex $hex @␀@¹
printf "$hex"² $hex $hex @␀@ @␀@ @␀@ @␀@
printf '%b' "$hex"³ $hex $hex $hex @␀@ @␀@ @␀@
echo -n "$hex2" $hex $hex $hex2 $hex2 $hex2 $hex
printf "$hex2" $hex $hex $hex $hex $hex $hex
printf '%b' "$hex2" $hex $hex $hex $hex $hex $hex
echo -n "$oct" @␀@ @ $oct $oct $oct \100␀\100¹
printf "$oct"* @␀@ @␀@ @␀@ @␀@ @␀@ @␀@
printf '%b' "$oct" @␀@ @ \100␀\100 @␀@ @␀@ \100␀\100
echo -n "$oct2" @␀@ @ $oct2 $oct2 $oct2 @␀@
printf "$oct2" ␈0␀0␈0¹ ␈0␀0␈0 ␈0␀0␈0 ␈0␀0␈0 ␈0␀0␈0 ␈0␀0␈0
printf '%b' "$oct2" @␀@ @ @␀@ @␀@ @␀@ @␀@
  • ᵃ These results are from running dash in an Ubuntu Docker container.
  • ᵇ This is from running dash on my host system, where it apparently interpreted the octal sequence as a C style (zero-terminated) string.
  • ¹ Italicized $var name stands for the unchanged literal value of the corresponding variable;
    @␀@ represents the expected byte sequence;
    stands for the null character (00) and stands for the backspace character (08);.
  • ² A POSIX-compliant printf is not supposed to recognize "hexadecimal character constants as defined in the ISO C standard".
  • ³ The b conversion specifier character is supposed to only convert \0ddd octal sequences, according to the POSIX spec.
  • * The only one that yields consistent results — printf "$oct".

Conclusion

The only approach that works consistently across all shells is using the octal escape sequence as the printf format string (printf '\100\000\100').

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment