Libc on macOS invokes Perl as a subprocess for string processing (2017)
twitter.com
twitter.com
/*
* We are the child; make /bin/sh expand `words'.
*/
(void)__libc_sigprocmask(SIG_SETMASK,
&oldsigblock, NULL);
if ((pdes[1] != STDOUT_FILENO ?
_dup2(pdes[1], STDOUT_FILENO) :
_fcntl(pdes[1], F_SETFD, 0)) < 0)
_exit(1);
if (_fcntl(pdesw[0], F_SETFD, 0) < 0)
_exit(1);
execl(_PATH_BSHELL, "sh", flags & WRDE_UNDEF ? "-u" : "+u",
"-c", "IFS=$1;eval \"$2\";"
"freebsd_wordexp -f \"$3\" ${4:+\"$4\"}",
"",
ifs != NULL ? ifs : " \t\n",
flags & WRDE_SHOWERR ? "" : "exec 2>/dev/null",
wfdstr,
flags & WRDE_NOCMD ? "-p" : "",
(char *)NULL);
_exit(1);
}https://git.musl-libc.org/cgit/musl/tree/src/misc/wordexp.c#...
This is regular BSD style, used in lots of places. Tabs for indentation, 4 spaces for wrapped lines.
> ternary operator
Totally fine here IMO. Would get really verbose without.
> without braces
Again, regular BSD style and a matter of taste.
Basically the coder here didn't just make up identifiers; they have connections to pervasive Unix concepts.
One way (in C or C++) would be to define constants:
#define DQ "\""
Then instead of "\"blah\" we have DQ "blah" DQ.http://xr.anadoxin.org/source/xref/macos-10.14-mojave/Libc-1...
The 'perl' code was a part of Libc v825.24, which seems to be included between 10.7 (Lion) and 10.8 (Mountain Lion).
Of course I still find it hilarious that even the old code did that!
So really, the entire premise of that POSIX function is horrible[1]. Just like system(), which also explicitly executes the given command line using the shell. These functions are not safe to use with untrusted input (e.g. remotely), ever.
EDIT: [1] But arguably only as horrible as calling out to the shell is in general. If you e.g. use it as part of a shell utility that assumes full POSIX-permissioned access to your user anyway, it's not unreasonable because there isn't any privilege escalation at all. Though I'd argue that in the case of system() it's probably more clear to the developer that a shell callout is happening. And also, that the "shell-style" expansion performed here is kinda muddily defined.
[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/w...
It should use Emacs instead.
> BUGS
> Do not pass untrusted user data to wordexp(), regardless of whether the WRDE_NOCMD flag is set. The wordexp() function attempts to detect input that would cause commands to be executed before passing it to the shell but it does not use the same parser so it may be fooled.
> The current wordexp() implementation does not recognize multibyte characters, since the shell (which it invokes to perform expansions) does not.
- /* XXX this is _not_ designed to be fast */
+ /* XXX this is _not_ designed to be safe */
[0] https://github.com/Apple-FOSS-Mirror/Libc/blob/2ca2ae7464771...It also has the nice effect of forcing user installed utilities to install in the /local/ variants (which user build projects should be doing on Linux iirc), so an OS update doesn’t overwrite user data.
Of course Perl, having fallen out of vogue, probably wouldn't be used today but it used to be everywhere so its footprint is still pretty large.
Also - I can't help but see the irony in shelling out to perl given experienced Perl developers always tell the less experienced ones to avoid shelling out from Perl if possible and to only do that as a last resort if there isn't an existing library to solve the problem.
The reason for that is obvious, right? By induction, shelling out from Perl would only result in the called process shelling back to Perl. So it's much better to just call that Perl code directly.
More experienced managers tell their devs to shell out to standard tools like sh, wget, curl, dig, mysqlclient and not use the builtin pure-perl libs. The tools are much better, the code is 10x smaller and faster, and you are getting updates for free (e.g. ssl). Even in C I very often call system("wget http://...") and avoid libcurl.
It's not NIH if you're advocating using CPAN modules or existing libraries.
Sure, use the right tool - but don't advocate to juniors a method that can lead to OS command injection because they're not experienced enough to know to, or how to, sanitise their inputs.
I did not contact that person anyways and I doubt there is a way. But at least knowing when I was blocked could help me deduce what might be the reason.
Honestly I do find this quite upsetting.
I believe the commonly accepted answer is "Yes, it's not my job to give you the necessary information to improve yourself". The same people who say that also often ask "Why aren't the people around me improving themselves?" :P
(Personally, I would prefer it if people pointed out my mistakes, and I do the same for others as a courtesy, not an obligation. I do understand if they don't have the energy to do that, but I think if they don't, then they forfeit the right to complain about a lack of improvement)
But that’s in no way comparable. When in the real world i screw up I can tell from people’s responses. Body language, their actions etc. In this case it’s just discovering at one point someone blocked one without any indication of when that happened and why without any indication.
//edit: also even weirder in an effort to see where our interactions might have been i found a tweet from 2014 by myself about the same topic: https://mobile.twitter.com/mitsuhiko/status/5264923088676700...
So how well does it reflect reality?
This repository is just a snapshot that somebody else prepared and uploaded to GitHub, but apparently it is not maintained.