CVE-2025-43370: A Path Buffer Overflow in rpcgen’s -Y Option
Apple Security Advisory: Xcode 26
Introduction
This is a buffer overflow I found in rpcgen’s rpc_main.c, part of Apple’s open-source developer_cmds, which ships inside Xcode’s developer tooling. The bug is in how rpcgen handles the -Y command line option, and the input that overruns the buffer is the path argument passed alongside that flag.
rpcgen is the RPC protocol compiler that turns a .x interface definition into C stubs. It has been part of the UNIX toolchain for decades, and it is exactly the kind of old utility that gets folded into a developer toolchain without much attention paid to its argument parsing. Because developer_cmds is a source of the tools Xcode installs, a bug here is a bug in the toolchain on a developer’s machine. Having looked at how rpcgen consumes its .x input, I turned to the code that parses its command line, which is where the -Y handling lives.
The Vulnerability
rpcgen accepts a -Y option that lets the user specify the directory where the C preprocessor (cpp) lives. The parser takes the path the user provides, copies it into a fixed static buffer, and then appends /cpp so it can invoke the preprocessor.
The buffer is a fixed static allocation sized to MAXPATHLEN + 1, and the copy is done with strcpy followed by strcat, neither of which respects the size of the destination:
static char pathbuf[MAXPATHLEN + 1];
...
strcpy(pathbuf, argv[i]);
strcat(pathbuf, "/cpp");
Here argv[i] is the argument that immediately follows -Y on the command line. There is no length check before the copy. The strcpy copies the entire path into pathbuf regardless of its length, and then the strcat appends the four characters of /cpp on top of whatever the strcpy already wrote. Neither call knows how large pathbuf is, so nothing prevents the combined write from running past the end of the buffer.
Root Cause
The -Y argument is fully user-controlled: it is simply the next token on the command line after -Y, taken verbatim as a filesystem path. That path is copied into pathbuf with an unbounded strcpy, and then strcat appends /cpp to it, again without bound. If the supplied path is near or beyond MAXPATHLEN, the strcpy alone can fill or exceed the buffer, and the subsequent strcat of /cpp writes past the end of pathbuf. Because pathbuf is declared static, it lives in the program’s global data segment, so the overflow corrupts adjacent global state rather than a stack frame. The fix is to replace the pair with the bounded strlcpy/strlcat, which take the destination size and truncate instead of overrunning.
Reproduction
Conceptually, the trigger is an invocation that passes -Y a directory path long enough to reach or exceed MAXPATHLEN, roughly 1100 characters, together with a valid .x file so that rpcgen proceeds far enough to act on the option. The path is copied verbatim into the MAXPATHLEN + 1 byte pathbuf by the unchecked strcpy, and the following strcat of /cpp then writes beyond the end of the buffer into the neighboring globals in the data segment.
Apple’s runtime crash detection observes the out-of-bounds write and terminates the process before the corruption can be used. The result is memory corruption in the program’s global data segment, which given control over the overflowing bytes is the kind of primitive that can be developed beyond a simple crash.