Skip to content

Commit

Permalink
Fix invalid XNU binaries generated by apelink in some edge cases (#…
Browse files Browse the repository at this point in the history
…1106)

* Fix `if...fi` generation in the generated APE shell script

A shell will fail with a syntax error on an empty `if` or `else` body.
That is, neither of these is allowed:

    # Empty `if`
    if [ ... ]; then
    fi

    # Empty `else`
    if [ ... ]; then
    ...
    else
    fi

There were two places where `apelink` could generate problematic `if`'s:

1. The XNU shell generation for aarch64 binaries when no loaders (either
   binary or source) are provided. They can't assimilate, so the resulting
   `else` body becomes empty.
   There is actually a code path guarded by the `gotsome` variable that
   inserts an extra `true` in this case, but the variable was never
   initialized, so in practice this code path didn't activate in my
   tests. This is fixed by initializing the variable.
2. The loader extraction code when no loaders are provided and XNU
   support is requested. This is fixed by adding a simliar code path
   that prevents an empty body from being generated.

* Update the apelink manual after commit d53c335

The `-s` option changed its meaning, but the docs weren't updated.
  • Loading branch information
dfyz authored Feb 23, 2024
1 parent e72a88e commit 99f0491
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions tool/build/apelink.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
" - 32: freebsd\n" \
" - 64: netbsd\n" \
"\n" \
" for example, `-s 0b1110001` may be used to\n" \
" for example, `-V 0b1110001` may be used to\n" \
" produce ELF binaries that only support the\n" \
" truly open unix systems. in this case when\n" \
" a single input executable is supplied, the\n" \
Expand All @@ -120,8 +120,8 @@
" also pass strings in a variety of intuitive\n" \
" supported representations. for example, bsd\n" \
" will enable freebsd+netbsd+openbsd and that\n" \
" string too is a legal input. the -s flag is\n" \
" also repeatable, e.g. `-s nt -s xnu` to use\n" \
" string too is a legal input. the -V flag is\n" \
" also repeatable, e.g. `-V nt -V xnu` to use\n" \
" the union of the two.\n" \
"\n" \
" since the support vector controls the file\n" \
Expand Down Expand Up @@ -988,7 +988,7 @@ static void GetOpts(int argc, char *argv[]) {
if (ParseSupportVector(optarg, &bits)) {
support_vector |= bits;
} else {
Die(prog, "unrecognized token passed to -s support vector flag");
Die(prog, "unrecognized token passed to -V support vector flag");
exit(1);
}
got_support_vector = true;
Expand Down Expand Up @@ -2036,7 +2036,7 @@ int main(int argc, char *argv[]) {
// let our shell script compile the ape loader on first run.
//
if (support_vector & _HOSTXNU) {
bool gotsome;
bool gotsome = false;
p = stpcpy(p, "else\n"); // if [ -d /Applications ]; then

// output native mach-o morph
Expand Down Expand Up @@ -2136,6 +2136,7 @@ int main(int argc, char *argv[]) {
}

// extract the ape loader for open platforms
bool gotsome = false;
if (inputs.n && (support_vector & _HOSTXNU)) {
p = stpcpy(p, "if [ ! -d /Applications ]; then\n");
}
Expand All @@ -2158,9 +2159,13 @@ int main(int argc, char *argv[]) {
"mv -f \"$t.$$\" \"$t\" ||exit\n");
p = stpcpy(p, "exec \"$t\" \"$o\" \"$@\"\n"
"fi\n");
gotsome = true;
}
}
if (inputs.n && (support_vector & _HOSTXNU)) {
if (!gotsome) {
p = stpcpy(p, "true\n");
}
p = stpcpy(p, "fi\n");
}

Expand Down

0 comments on commit 99f0491

Please sign in to comment.