switchbrew / nx-hbloader

Host process for loading Switch homebrew NROs
ISC License
349 stars 76 forks source link

Argument parsing (& associated HBABI spec) is problematic #13

Open misson20000 opened 5 years ago

misson20000 commented 5 years ago

The Problem

As defined by the HBABI, the Argv key has an unused (formerly argc) field, and an argv field. When originally defined, it was unclear what exactly the argv field represented. I know that I personally thought the argv contained a pointer to an array of pointers to characters, and that argc was intended to indicate how long this array was.

The spec was later slightly clarified to indicate that the argv field contains a string pointer, and even later, the argc field was removed, but the argv field was left with an incomplete and ambiguous specification for how exactly arguments are separated.

The current libnx implementation separates arguments by spaces, except for when they are "quoted". I don't know if this argument parsing code was designed to patch the Nintendo implementation or not, but either way, this behavior is not defined in the HBABI spec. Additionally, this logic does not provide a mechanism to escape quotation marks and does not match the behavior of common shells (bash) when quotation marks are introduced in strange places. This means that given an argc+argv pair, there is no way to reliably encode and pass it as an HBABI key in such a way that it will be decoded back to the exact same pair.

A Solution

The current argument parsing behavior should be defined in the HBABI spec, but that doesn't address the problem of no perfect escaping. The argument parsing can't be changed without breaking compatibility, and a homebrew loader has no way of knowing whether an application will have correct argument parsing logic or not. I don't think that argument parsing should've ever been the application's job in the first place, so I'd suggest we define a new HBABI key that passes arguments in argc/argv format, avoiding the argument parsing problem altogether. Compatibility can be retained by having homebrew loaders attempt to pack argc/argv into a constant string for the old Argv key, while also passing a newer extended Argv key. The extended argv key can be marked mandatory if perfect argv packing was not possible.

Argument Parsing Inconsistency Examples

foo "" bar

Bash:

Libnx:

foo" bar"

Bash:

Libnx

plutooo commented 5 years ago

I believe the libnx argv parsing is equivalent to what Nintendo does for its "loader-based argv", but I could be wrong on that. Anyway that's what we were trying to emulate

yellows8 commented 5 years ago

What's the use-case for this?

@plutooo exactly

misson20000 commented 5 years ago

Use case is perfectly forwarding arguments from a command line to a homebrew (like nxlink tries to do)

yellows8 commented 5 years ago

Perhaps you could just use: strncpy(tmpbuf, envGetArgv(), ...)

misson20000 commented 5 years ago

What? I'm not sure what you're suggesting there. I want to have a command line tool that passes its arguments (already parsed by the shell), over some kind of connection, to a program on the switch which can pass those arguments as an HBABI key to any homebrew application, without altering the arguments themselves at all.

yellows8 commented 5 years ago

nvm