ww: make allocation failures stage-equivalent

This commit is contained in:
2026-08-13 08:19:29 +09:00
parent b58c1f152a
commit 059550e00f
2 changed files with 97 additions and 33 deletions

View File

@@ -1728,8 +1728,14 @@ sep_scan_file(struct sepgraph *g, int pi, const char *file,
break;
}
{
errno = 0;
char *canon = realpath(ipath, NULL);
if (canon == NULL) {
if (errno == ENOMEM) {
sep_fail_nomem();
rc = -1;
break;
}
errorf(u->pos, "cannot canonicalize package '%s'", name);
rc = -1;
break;
@@ -2130,8 +2136,12 @@ sep_reverse_import_base(const struct sepgraph *g, const struct seppkg *pkg,
if (root == NULL) return sep_fail_nomem();
memcpy(root, p, n);
root[n] = '\0';
errno = 0;
char *canon = n == 0 ? NULL : realpath(root, NULL);
int canon_errno = n == 0 ? 0 : errno;
free(root);
if (canon == NULL && canon_errno == ENOMEM)
return sep_fail_nomem();
if (canon != NULL) {
size_t rn = strlen(canon);
const char *rel = NULL;
@@ -2149,9 +2159,16 @@ sep_reverse_import_base(const struct sepgraph *g, const struct seppkg *pkg,
char located[PATH_MAX];
if (locate_import(searchpath, rel, located,
sizeof located)) {
errno = 0;
char *selected = realpath(located, NULL);
int selected_errno = errno;
int same = selected != NULL
&& strcmp(selected, pkg->canon) == 0;
if (selected == NULL
&& selected_errno == ENOMEM) {
free(canon);
return sep_fail_nomem();
}
free(selected);
if (same) { free(canon); return 1; }
}
@@ -2896,7 +2913,12 @@ build_one_sep_impl(const char *src, int entry_is_dir,
g->support_context = sep_context_for(g, toolsrcdir, NULL,
toolsrcdir);
if (g->support_context < 0) return 1;
errno = 0;
char *tc = realpath(tpath, NULL);
if (tc == NULL && errno == ENOMEM) {
sep_fail_nomem();
return 1;
}
int collision = 0;
for (int i = 0; i < nproducts; i++) {
int root_is_support = tc != NULL
@@ -2914,7 +2936,13 @@ build_one_sep_impl(const char *src, int entry_is_dir,
"test", userpath, sizeof userpath)) {
userdir = 1;
(void)userdir;
errno = 0;
char *uc = realpath(userpath, NULL);
if (uc == NULL && errno == ENOMEM) {
free(tc);
sep_fail_nomem();
return 1;
}
if (tc != NULL && uc != NULL
&& strcmp(tc, uc) != 0)
collision = 1;
@@ -3704,22 +3732,24 @@ do_build(int argc, char **argv)
{
const char *src = NULL;
struct seplinkflags linkflags = {0};
size_t incsz = 1;
for (int i = 0; i < argc; i++) incsz += strlen(argv[i]) + 1;
char incs[incsz];
memset(incs, 0, sizeof incs);
size_t incsz = 0;
char *incs = NULL;
if (include_buffer_for_args(argc, argv, &incs, &incsz) < 0) return 1;
char outflag[PATH_MAX] = {0};
char workdir[PATH_MAX] = {0};
int emit_asm = 0;
int package_only = 0;
if (parse_build_flags("build", argc, argv, incs, sizeof incs,
if (parse_build_flags("build", argc, argv, incs, incsz,
&linkflags,
outflag, sizeof outflag, workdir, sizeof workdir,
&src, &emit_asm, &package_only) < 0)
&src, &emit_asm, &package_only) < 0) {
free(incs);
return 2;
}
if (src == NULL) src = ".";
if (package_only && emit_asm) {
fprintf(stderr, "ww build: -p and -S cannot be combined\n");
free(incs);
return 2;
}
struct stat requested;
@@ -3728,10 +3758,12 @@ do_build(int argc, char **argv)
int is_dir = 0;
if (!resolve_module(src, incs, resolved, sizeof resolved, &is_dir)) {
fprintf(stderr, "ww build: cannot find module %s\n", src);
free(incs);
return 1;
}
if (package_only && !is_dir) {
fprintf(stderr, "ww build: -p needs a package directory\n");
free(incs);
return 2;
}
char out[PATH_MAX];
@@ -3752,9 +3784,11 @@ do_build(int argc, char **argv)
basename_no_ext(resolved, out, sizeof out);
}
const char *root_identity = !literal && is_dir ? src : NULL;
return build_one_sep(resolved, is_dir, root_identity, out, objstem, incs,
int rc = build_one_sep(resolved, is_dir, root_identity, out, objstem, incs,
&linkflags, package_only, 0, SEP_VARIANT_PRODUCTION, NULL, emit_asm,
1, workdir);
free(incs);
return rc;
}
static int
@@ -3762,15 +3796,14 @@ do_run(int argc, char **argv)
{
const char *src = NULL;
struct seplinkflags linkflags = {0};
size_t incsz = 1;
for (int i = 0; i < argc; i++) incsz += strlen(argv[i]) + 1;
char incs[incsz];
memset(incs, 0, sizeof incs);
size_t incsz = 0;
char *incs = NULL;
if (include_buffer_for_args(argc, argv, &incs, &incsz) < 0) return 1;
char outflag[PATH_MAX] = {0}; /* -o accepted+ignored: run always uses the temp */
int next = parse_build_flags("run", argc, argv, incs, sizeof incs,
int next = parse_build_flags("run", argc, argv, incs, incsz,
&linkflags,
outflag, sizeof outflag, NULL, 0, &src, NULL, NULL);
if (next < 0) return 2;
if (next < 0) { free(incs); return 2; }
if (src == NULL) src = ".";
struct stat requested;
int literal = stat(src, &requested) == 0;
@@ -3778,22 +3811,29 @@ do_run(int argc, char **argv)
int is_dir = 0;
if (!resolve_module(src, incs, resolved, sizeof resolved, &is_dir)) {
fprintf(stderr, "ww run: cannot find module %s\n", src);
free(incs);
return 1;
}
char tmpdir[PATH_MAX], tmp[PATH_MAX];
snprintf(tmpdir, sizeof tmpdir, "/tmp/ww_run_%d", getpid());
if (mkdir(tmpdir, 0700) != 0) {
fprintf(stderr, "ww: cannot create temporary directory %s\n", tmpdir);
free(incs);
return 1;
}
int tn = snprintf(tmp, sizeof tmp, "%s/main", tmpdir);
if (tn < 0 || (size_t)tn >= sizeof tmp) return 1;
if (tn < 0 || (size_t)tn >= sizeof tmp) {
free(incs);
return 1;
}
/* The freshly acquired directory owns both the executable and the
* adjacent main.sepwork tree. Nothing outside it is adopted or removed. */
const char *root_identity = !literal && is_dir ? src : NULL;
if (build_one_sep(resolved, is_dir, root_identity, tmp, tmp, incs,
int buildrc = build_one_sep(resolved, is_dir, root_identity, tmp, tmp, incs,
&linkflags,
0, 0, SEP_VARIANT_PRODUCTION, NULL, 0, 0, NULL) != 0) {
0, 0, SEP_VARIANT_PRODUCTION, NULL, 0, 0, NULL);
free(incs);
if (buildrc != 0) {
if (unlink(tmp) != 0 && errno != ENOENT)
fputs("ww: cannot remove temporary output\n", stderr);
if (rmdir(tmpdir) != 0)