shithub: scc

Download patch

ref: 1623dbdd55d0ee760c4a1c17c5881f7ca0153186
parent: 845a4d450d705c86e557494e4661abddf4f157be
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Aug 27 11:58:16 EDT 2019

[nm] Improve error handling

There is a centralized check of errors now.

--- a/include/scc/scc/mach.h
+++ b/include/scc/scc/mach.h
@@ -68,6 +68,7 @@
 extern long armember(FILE *fp, char *member);
 
 extern int objtype(FILE *fp, char **name);
-extern Obj *objnew(int type);
+extern Obj *newobj(int type);
+extern void delobj(Obj *obj);
 extern int readobj(Obj *obj, FILE *fp);
 extern int getsym(Obj *obj, long *index, Symbol *sym);
--- a/src/cmd/nm.c
+++ b/src/cmd/nm.c
@@ -121,36 +121,32 @@
 	size_t n, size;
 	int type = sym->type;
 
-	if (type == '?' || type == 'N')
-		return 1;
+	if (type == '?'
+	|| type == 'N'
+	|| uflag && type != 'U'
+	|| gflag && !isupper(type)) {
+		return 0;
+	}
 
-	if (uflag && type != 'U')
-		return 1;
-
-	if (gflag && !isupper(type))
-		return 1;
-
 	n = tbl->nsyms+1;
-	if (n == 0 || n > SIZE_MAX / sizeof(*p))
-		return 0;
 	size = n *sizeof(*p);
-
 	p = realloc(tbl->buf, size);
 	s = malloc(sizeof(*s));
 	if (!p || !s) {
-		error("out of memory");
-		exit(EXIT_FAILURE);
+		free(p);
+		free(s);
+		error(strerror(errno));
+		return -1;
 	}
 
 	*s = *sym;
 	tbl->buf = p;
 	p[tbl->nsyms++] = s;
-
-	return 1;
+	return 0;
 }
 
 static void
-newobject(FILE *fp, int type)
+nmobj(FILE *fp, int type)
 {
 	int err = 1;
 	long i;
@@ -158,46 +154,54 @@
 	Symbol sym;
 	struct symtbl tbl = {NULL, 0};
 
-	if ((obj = objnew(type)) == NULL) {
-		error("out of memory");
-		exit(EXIT_FAILURE);
+	if ((obj = newobj(type)) == NULL) {
+		error(strerror(errno));
+		goto err1;
 	}
 
-	if (readobj(obj, fp) < 0)
-		goto error;
+	if (readobj(obj, fp) < 0) {
+		error(strerror(errno));
+		goto err2;
+	}
 
-	for (i = 0; getsym(obj, &i, &sym); i++)
-		newsym(&sym, &tbl);
+	for (i = 0; getsym(obj, &i, &sym) != -1; i++) {
+		if (newsym(&sym, &tbl) < 0)
+			goto err3;
+	}
 
 	printsyms(tbl.buf, tbl.nsyms);
 	err = 0;
 
-error:
-	(*obj->ops->del)(obj);
+err3:
 	free(tbl.buf);
+err2:
+	delobj(obj);
+err1: 
 	if (err)
 		error("object file corrupted");
 }
 
 static void
-newlib(FILE *fp)
+nmlib(FILE *fp)
 {
 	int t;
 	long off, cur;
 	char memb[SARNAM+1];
 
-	while (!feof(fp)) {
+	for (;;) {
 		cur = ftell(fp);
 		off = armember(fp, memb);
 		switch (off) {
 		case -1:
 			error("library corrupted");
+			if (ferror(fp))
+				error(strerror(errno));
 		case 0:
 			return;
 		default:
 			membname = memb;
 			if ((t = objtype(fp, NULL)) != -1)
-				newobject(fp, t);
+				nmobj(fp, t);
 			membname = NULL;
 			fseek(fp, cur, SEEK_SET);
 			fseek(fp, off, SEEK_CUR);
@@ -204,8 +208,6 @@
 			break;
 		}
 	}
-
-	error("library corrupted:%s", strerror(errno));
 }
 
 static void
@@ -223,15 +225,12 @@
 	}
 
 	if ((t = objtype(fp, NULL)) != -1)
-		newobject(fp, t);
+		nmobj(fp, t);
 	else if (archive(fp))
-		newlib(fp);
+		nmlib(fp);
 	else
 		error("bad format");
 
-	if (ferror(fp))
-		error(strerror(errno));
-
 	fclose(fp);
 }
 
@@ -287,7 +286,7 @@
 			nm(*argv);
 	}
 
-	if (fflush(stdout)) {
+	if (fflush(stdout) == EOF) {
 		fprintf(stderr,
 		        "nm: error writing in output:%s\n",
 		        strerror(errno));
--- a/src/libmach/Makefile
+++ b/src/libmach/Makefile
@@ -5,7 +5,8 @@
 TARGET = $(LIBDIR)/libmach.a
 
 OBJS = mach.o \
-       objnew.o \
+       newobj.o \
+       delobj.o \
        objpos.o \
        archive.o \
        armember.o \
--- a/src/libmach/armember.c
+++ b/src/libmach/armember.c
@@ -1,3 +1,4 @@
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -31,14 +32,18 @@
 	if (fread(&hdr, sizeof(hdr), 1, fp) != 1)
 		return (feof(fp)) ? 0 : -1;
 
-	if (strncmp(hdr.ar_fmag, ARFMAG, sizeof(hdr.ar_fmag)))
+	if (strncmp(hdr.ar_fmag, ARFMAG, sizeof(hdr.ar_fmag))) {
+		errno = ERANGE;
 		return -1;
+	}
 
 	siz = strtol(hdr.ar_size, NULL, 0);
 	if (siz & 1)
 		siz++;
-	if (siz == 0)
+	if (siz == 0) {
+		errno = ERANGE;
 		return -1;
+	}
 
 	getfname(&hdr, member);
 
--- a/src/libmach/coff32/coff32del.c
+++ b/src/libmach/coff32/coff32del.c
@@ -18,6 +18,4 @@
 	}
 	free(obj->data);
 	obj->data = NULL;
-
-	free(obj);
 }
--- a/src/libmach/coff32/coff32getsym.c
+++ b/src/libmach/coff32/coff32getsym.c
@@ -1,4 +1,5 @@
 #include <ctype.h>
+#include <errno.h>
 #include <stdio.h>
 
 #include <scc/mach.h>
@@ -59,8 +60,10 @@
 	SYMENT *ent;
 	Coff32 *coff = obj->data;
 
-	if (*idx >= coff->hdr.f_nsyms)
-		return 0;
+	if (*idx >= coff->hdr.f_nsyms) {
+		errno = ERANGE;
+		return -1;
+	}
 
 	ent = &coff->ents[n];
 	sym->name = symname(coff, ent);
@@ -70,5 +73,5 @@
 	sym->index = n;
 	*idx += ent->n_numaux;
 
-	return 1;
+	return 0;
 }
--- a/src/libmach/coff32/coff32read.c
+++ b/src/libmach/coff32/coff32read.c
@@ -1,5 +1,6 @@
 #include <assert.h>
 #include <ctype.h>
+#include <errno.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -359,8 +360,10 @@
 
 	for (i = 0; i < hdr->f_nsyms; i++) {
 		SYMENT *ent = &coff->ents[i];
-		if (ent->n_zeroes != 0 && ent->n_offset > coff->strsiz)
+		if (ent->n_zeroes != 0 && ent->n_offset > coff->strsiz) {
+			errno = ERANGE;
 			return -1;
+		}
 	}
 
 	return 0;
--- /dev/null
+++ b/src/libmach/newobj.c
@@ -1,0 +1,33 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <scc/mach.h>
+
+#include "libmach.h"
+
+Obj *
+newobj(int type)
+{
+	Obj *obj;
+	int fmt;
+
+	fmt = FORMAT(type);
+	if (fmt >= NFORMATS) {
+		errno = ERANGE;
+		return NULL;
+	}
+
+	if ((obj = malloc(sizeof(*obj))) == NULL)
+		return NULL;
+
+	obj->type = type;
+	obj->ops = objops[fmt];
+	if ((*obj->ops->new)(obj) < 0) {
+		free(obj);
+		return NULL;
+	}
+
+	return obj;
+}
--- a/src/libmach/objnew.c
+++ /dev/null
@@ -1,33 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/mach.h>
-
-#include "libmach.h"
-
-Obj *
-objnew(int type)
-{
-	Obj *obj;
-	int fmt;
-	Objops *ops;
-
-	fmt = FORMAT(type);
-	if (fmt >= NFORMATS)
-		return NULL;
-
-	if ((obj = malloc(sizeof(*obj))) == NULL)
-		return NULL;
-
-	obj->type = type;
-	ops = objops[fmt];
-	obj->ops = ops;
-
-	if ((*ops->new)(obj) < 0) {
-		free(obj);
-		return NULL;
-	}
-
-	return obj;
-}