commit c7c6f38c144142563e135eceb5daed492c203a85
parent 14bc8a3883663656cd4254567a978002c062992d
Author: Louis Burda <quent.burda@gmail.com>
Date: Fri, 25 Jun 2021 01:51:22 +0200
fix free() of potentially uninitialized pointer and minor refactors in service
Diffstat:
8 files changed, 102 insertions(+), 98 deletions(-)
diff --git a/checker/src/checker.py b/checker/src/checker.py
@@ -120,7 +120,7 @@ class STLDoctorChecker(BaseChecker):
else:
content = b"solid\n"
facet_count = rand.randint(4, 30)
- indent = bytes([rand.choice(b"\t\n ") for i in range(rand.randint(1, 4))])
+ indent = bytes([rand.choice(b"\t ") for i in range(rand.randint(1, 4))])
for fi in range(facet_count):
if malformed and randchoice == 0: # malformed by wrong keyword
content += indent * 1 + b"facet nornal "
diff --git a/checker/test.sh b/checker/test.sh
@@ -44,7 +44,7 @@ try() {
python3 src/checker.py -j run -v "$variant" -x 4000 \
--flag ENOTESTFLAG123= --flag_regex 'ENO.*=' -i $taskid \
${@:3} "$cmd" > "$tmpfile"
- res="$(cat $tmpfile | grep -a Result: | tail -n1 | grep -a -o OK)"
+ res="$(cat $tmpfile | grep -a -o 'Result: .*' | tail -n1 | cut -d' ' -f2)"
fi
if [ "$res" != "OK" ]; then
newfile="fails/err-$pid"
diff --git a/service/src/main.c b/service/src/main.c
@@ -43,7 +43,7 @@ struct command commands[] = {
{ "auth", auth_cmd, "Login to upload files to a private dir." }
};
-struct parseinfo cached;
+struct parseinfo cached = { 0 };
char *resultdir;
int echo = 0, loggedin = 0;
@@ -52,7 +52,7 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize)
{
char *dirpath = NULL, *infopath = NULL, *modelpath = NULL;
FILE *f = NULL;
- int status = 0;
+ int status = OK;
DIR *d;
if (loggedin)
@@ -64,12 +64,12 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize)
modelpath = aprintf("%s/%s", dirpath, "model");
if (!(f = fopen(modelpath, "w+"))) goto fail;
if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail;
- NFCLOSE(f);
+ FCLOSE(f);
infopath = aprintf("%s/%s", dirpath, "info");
if (!(f = fopen(infopath, "w+"))) goto fail;
if (save_info(info, f) != OK) goto fail;
- NFCLOSE(f);
+ FCLOSE(f);
exit:
if (f) fclose(f);
@@ -85,7 +85,7 @@ fail:
if (modelpath) remove(modelpath);
if (dirpath) remove(dirpath);
- status = 1;
+ status = FAIL;
goto exit;
}
@@ -99,9 +99,9 @@ access_authorized(const char *file)
int
handle_download(const char *scandir)
{
- char *infopath, *modelpath;
+ char *infopath = NULL, *modelpath = NULL;
size_t i, size;
- int status = 0;
+ int status = OK;
FILE *f;
infopath = aprintf("%s/%s", scandir, "info");
@@ -109,12 +109,13 @@ handle_download(const char *scandir)
ERR("Selected result is missing!\n");
goto fail;
}
+
free_info(&cached);
if (load_info(&cached, f) != OK) {
ERR("Failed to parse info file!\n");
goto fail;
}
- NFCLOSE(f);
+ FCLOSE(f);
print_info(&cached);
@@ -134,7 +135,7 @@ handle_download(const char *scandir)
printf("Here you go.. (%liB)\n", size);
while ((i = getc(f)) != EOF)
putc(i, stdout);
- NFCLOSE(f);
+ FCLOSE(f);
}
exit:
@@ -144,7 +145,7 @@ exit:
return status;
fail:
- status = 1;
+ status = FAIL;
goto exit;
}
@@ -276,12 +277,12 @@ search_cmd(const char *arg)
}
scandir = aprintf("%s/%s", resultdir, paths[which]);
- if (handle_download(scandir)) goto cleanup;
- NFREE(scandir);
+ if (handle_download(scandir) != OK) goto cleanup;
+ FREE(scandir);
}
cleanup:
- free(scandir);
+ FREE(scandir);
for (i = 0; i < pathc; i++) free(paths[i]);
free(paths);
@@ -309,13 +310,16 @@ list_cmd(const char *arg)
path = aprintf("%s/%s/info", resultdir, de->d_name);
if ((f = fopen(path, "r")) && load_info(&info, f) == OK) {
print_info(&info);
+ free_info(&info);
} else {
- ERR("Failed to read saved file info!\n");
+ ERR("Failed to read file info!\n");
}
if (f) fclose(f);
free(path);
}
}
+
+ closedir(d);
}
void
@@ -345,7 +349,7 @@ auth_cmd(const char *arg)
free(resultdir);
resultdir = ndir;
loggedin = 1;
- cached.valid = 0;
+ free_info(&cached);
}
void
@@ -359,7 +363,6 @@ cleanexit()
int
main()
{
- struct command *c;
const char *cmd, *envstr;
char *cp, *arg;
int exit, i, cmdlen;
@@ -389,9 +392,9 @@ main()
cmdlen = cp ? cp - cmd : strlen(cmd);
for (i = 0; i < ARRSIZE(commands); i++) {
- c = &commands[i];
- if (!strncmp(c->name, cmd, cmdlen) && !c->name[cmdlen]) {
- c->func(arg);
+ if (!strncmp(commands[i].name, cmd, cmdlen)
+ && !commands[i].name[cmdlen]) {
+ commands[i].func(arg);
break;
}
}
diff --git a/service/src/stlfile.c b/service/src/stlfile.c
@@ -134,7 +134,7 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
stack_push(&states, STATE_SOLID);
if (stack_ind(&states, KW_SOLID_BEGIN) != -1) {
FMT_ERR("Multiple nested solids!\n");
- goto format_error;
+ goto fail;
}
tmp = bp;
if (!consume_keyword(&bp)
@@ -148,14 +148,14 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
if ((kw = stack_pop(&states)) != STATE_SOLID) {
FMT_ERR("Improper nesting, parent: %s\n",
kwmap[kw].str);
- goto format_error;
+ goto fail;
}
tmp = bp;
if (info->solidname && !consume_keyword(&bp)
&& (arg = consume_arg(&bp, &end))) {
if (strncmp(info->solidname, arg, end - arg)) {
FMT_ERR("Solid names do not match!\n");
- goto format_error;
+ goto fail;
}
} else {
bp = tmp;
@@ -165,14 +165,14 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
stack_push(&states, STATE_LOOP);
if (stack_ind(&states, KW_LOOP_BEGIN) != -1) {
FMT_ERR("Multiple nested loops!\n");
- goto format_error;
+ goto fail;
}
break;
case KW_LOOP_END:
if ((kw = stack_pop(&states)) != STATE_LOOP) {
FMT_ERR("Improper nesting, parent: %s\n",
kwmap[kw].str);
- goto format_error;
+ goto fail;
}
info->loopcount++;
break;
@@ -180,17 +180,17 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
stack_push(&states, STATE_FACET);
if (stack_ind(&states, KW_LOOP_BEGIN) != -1) {
FMT_ERR("Multiple nested facets!\n");
- goto format_error;
+ goto fail;
}
for (i = 0; i < 3; i++) {
if (!(arg = consume_arg(&bp, &end))) {
FMT_ERR("Facet with < 3 args!\n");
- goto format_error;
+ goto fail;
}
farg = strtof(arg, &tmp);
if (!isws(*tmp)) {
FMT_ERR("Facet arg '%s'\n", arg);
- goto format_error;
+ goto fail;
}
}
break;
@@ -198,19 +198,19 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
if ((kw = stack_pop(&states)) != STATE_FACET) {
FMT_ERR("Improper nesting, parent: %s\n",
kwmap[kw].str);
- goto format_error;
+ goto fail;
}
break;
case KW_VERTEX:
for (i = 0; i < 3; i++) {
if (!(arg = consume_arg(&bp, &end))) {
FMT_ERR("Vertex with < 3 args\n");
- goto format_error;
+ goto fail;
}
farg = strtof(arg, &tmp);
if (!isws(*tmp)) {
FMT_ERR("Vertex arg '%s'\n", arg);
- goto format_error;
+ goto fail;
}
info->bbmin[i] = MIN(info->bbmin[i], farg);
info->bbmax[i] = MAX(info->bbmax[i], farg);
@@ -219,26 +219,26 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
case KW_UNKNOWN:
prev = skipws(prev);
FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, prev);
- goto format_error;
+ goto fail;
}
prev = bp;
}
if (states.count) {
FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, bp);
- goto format_error;
+ goto fail;
}
bp = skipws(bp);
if (*bp) {
FMT_ERR("Extraneous data at end of file\n");
- goto format_error;
+ goto fail;
}
stack_free(&states);
return OK;
-format_error:
+fail:
stack_free(&states);
return FAIL;
}
@@ -305,7 +305,7 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len)
return OK;
fail:
- NFREE(info->solidname);
+ FREE(info->solidname);
return FAIL;
}
@@ -316,7 +316,8 @@ parse_file(struct parseinfo *info, char *buf, size_t len)
const char *resp;
char *bp;
- free_info(info);
+ if (info->valid)
+ free_info(info);
if (len < 10) {
ERR("File too small!\n");
@@ -331,8 +332,6 @@ parse_file(struct parseinfo *info, char *buf, size_t len)
: parse_file_bin(info, buf, len);
if (status == FAIL) return FAIL;
- if (!info->solidname) info->solidname = checkp(strdup(""));
-
if (!info->modelname) {
resp = ask("Please enter your model name: ");
if (strlen(resp) < 4) {
@@ -342,6 +341,8 @@ parse_file(struct parseinfo *info, char *buf, size_t len)
info->modelname = checkp(strdup(resp));
}
+ if (!info->solidname) info->solidname = checkp(strdup(""));
+
info->hash = checkp(strdup(mhash(info->modelname, -1)));
return OK;
@@ -406,12 +407,9 @@ print_info(struct parseinfo *info)
{
int i, k;
-#define FILTERCHAR(c) ((c) >= 32 ? (c) : ' ')
-
printf(" === Model info === \n");
printf(" File Size: %u\n", info->filesize);
-
if (info->type == TYPE_BIN) {
printf(" Header:\n");
for (i = 0; i < 80; i += k) {
@@ -420,11 +418,10 @@ print_info(struct parseinfo *info)
printf(" %02x", (uint8_t) info->header[i+k]);
printf(" | ");
for (k = 0; k < MIN(80 - i, 20); k++)
- printf("%c", FILTERCHAR(info->header[i+k]));
+ putchar(PRINTABLE(info->header[i+k]));
printf("\n");
}
}
-
printf(" Model ID: %s\n", info->hash);
printf(" Model Name: %s\n", info->modelname);
printf(" Solid Name: %s\n", info->solidname);
@@ -442,9 +439,9 @@ print_info(struct parseinfo *info)
void
free_info(struct parseinfo *info)
{
- NFREE(info->hash);
- NFREE(info->modelname);
- NFREE(info->solidname);
+ FREE(info->hash);
+ FREE(info->modelname);
+ FREE(info->solidname);
info->valid = 0;
}
diff --git a/service/src/util.h b/service/src/util.h
@@ -11,10 +11,12 @@
#define MIN(x,y) ((x) > (y) ? (y) : (x))
#define MAX(x,y) ((x) < (y) ? (y) : (x))
+#define PRINTABLE(c) ((c) >= 32 ? (c) : ' ')
+
#define ERR(...) printf("ERR: " __VA_ARGS__)
-#define NFREE(p) do { free(p); p = NULL; } while (0)
-#define NFCLOSE(f) do { fclose(f); f = NULL; } while (0)
+#define FREE(p) do { free(p); p = NULL; } while (0)
+#define FCLOSE(f) do { if (f) fclose(f); f = NULL; } while (0)
#define MHASHLEN 40
diff --git a/src/main.c b/src/main.c
@@ -43,7 +43,7 @@ struct command commands[] = {
{ "auth", auth_cmd, "Login to upload files to a private dir." }
};
-struct parseinfo cached;
+struct parseinfo cached = { 0 };
char *resultdir;
int echo = 0, loggedin = 0;
@@ -52,7 +52,7 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize)
{
char *dirpath = NULL, *infopath = NULL, *modelpath = NULL;
FILE *f = NULL;
- int status = 0;
+ int status = OK;
DIR *d;
if (loggedin)
@@ -64,12 +64,12 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize)
modelpath = aprintf("%s/%s", dirpath, "model");
if (!(f = fopen(modelpath, "w+"))) goto fail;
if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail;
- NFCLOSE(f);
+ FCLOSE(f);
infopath = aprintf("%s/%s", dirpath, "info");
if (!(f = fopen(infopath, "w+"))) goto fail;
if (save_info(info, f) != OK) goto fail;
- NFCLOSE(f);
+ FCLOSE(f);
exit:
if (f) fclose(f);
@@ -85,7 +85,7 @@ fail:
if (modelpath) remove(modelpath);
if (dirpath) remove(dirpath);
- status = 1;
+ status = FAIL;
goto exit;
}
@@ -99,9 +99,9 @@ access_authorized(const char *file)
int
handle_download(const char *scandir)
{
- char *infopath, *modelpath;
+ char *infopath = NULL, *modelpath = NULL;
size_t i, size;
- int status = 0;
+ int status = OK;
FILE *f;
infopath = aprintf("%s/%s", scandir, "info");
@@ -109,12 +109,13 @@ handle_download(const char *scandir)
ERR("Selected result is missing!\n");
goto fail;
}
+
free_info(&cached);
if (load_info(&cached, f) != OK) {
ERR("Failed to parse info file!\n");
goto fail;
}
- NFCLOSE(f);
+ FCLOSE(f);
print_info(&cached);
@@ -134,7 +135,7 @@ handle_download(const char *scandir)
printf("Here you go.. (%liB)\n", size);
while ((i = getc(f)) != EOF)
putc(i, stdout);
- NFCLOSE(f);
+ FCLOSE(f);
}
exit:
@@ -144,7 +145,7 @@ exit:
return status;
fail:
- status = 1;
+ status = FAIL;
goto exit;
}
@@ -276,12 +277,12 @@ search_cmd(const char *arg)
}
scandir = aprintf("%s/%s", resultdir, paths[which]);
- if (handle_download(scandir)) goto cleanup;
- NFREE(scandir);
+ if (handle_download(scandir) != OK) goto cleanup;
+ FREE(scandir);
}
cleanup:
- free(scandir);
+ FREE(scandir);
for (i = 0; i < pathc; i++) free(paths[i]);
free(paths);
@@ -309,13 +310,16 @@ list_cmd(const char *arg)
path = aprintf("%s/%s/info", resultdir, de->d_name);
if ((f = fopen(path, "r")) && load_info(&info, f) == OK) {
print_info(&info);
+ free_info(&info);
} else {
- ERR("Failed to read saved file info!\n");
+ ERR("Failed to read file info!\n");
}
if (f) fclose(f);
free(path);
}
}
+
+ closedir(d);
}
void
@@ -345,7 +349,7 @@ auth_cmd(const char *arg)
free(resultdir);
resultdir = ndir;
loggedin = 1;
- cached.valid = 0;
+ free_info(&cached);
}
void
@@ -359,7 +363,6 @@ cleanexit()
int
main()
{
- struct command *c;
const char *cmd, *envstr;
char *cp, *arg;
int exit, i, cmdlen;
@@ -389,9 +392,9 @@ main()
cmdlen = cp ? cp - cmd : strlen(cmd);
for (i = 0; i < ARRSIZE(commands); i++) {
- c = &commands[i];
- if (!strncmp(c->name, cmd, cmdlen) && !c->name[cmdlen]) {
- c->func(arg);
+ if (!strncmp(commands[i].name, cmd, cmdlen)
+ && !commands[i].name[cmdlen]) {
+ commands[i].func(arg);
break;
}
}
diff --git a/src/stlfile.c b/src/stlfile.c
@@ -134,7 +134,7 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
stack_push(&states, STATE_SOLID);
if (stack_ind(&states, KW_SOLID_BEGIN) != -1) {
FMT_ERR("Multiple nested solids!\n");
- goto format_error;
+ goto fail;
}
tmp = bp;
if (!consume_keyword(&bp)
@@ -148,14 +148,14 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
if ((kw = stack_pop(&states)) != STATE_SOLID) {
FMT_ERR("Improper nesting, parent: %s\n",
kwmap[kw].str);
- goto format_error;
+ goto fail;
}
tmp = bp;
if (info->solidname && !consume_keyword(&bp)
&& (arg = consume_arg(&bp, &end))) {
if (strncmp(info->solidname, arg, end - arg)) {
FMT_ERR("Solid names do not match!\n");
- goto format_error;
+ goto fail;
}
} else {
bp = tmp;
@@ -165,14 +165,14 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
stack_push(&states, STATE_LOOP);
if (stack_ind(&states, KW_LOOP_BEGIN) != -1) {
FMT_ERR("Multiple nested loops!\n");
- goto format_error;
+ goto fail;
}
break;
case KW_LOOP_END:
if ((kw = stack_pop(&states)) != STATE_LOOP) {
FMT_ERR("Improper nesting, parent: %s\n",
kwmap[kw].str);
- goto format_error;
+ goto fail;
}
info->loopcount++;
break;
@@ -180,17 +180,17 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
stack_push(&states, STATE_FACET);
if (stack_ind(&states, KW_LOOP_BEGIN) != -1) {
FMT_ERR("Multiple nested facets!\n");
- goto format_error;
+ goto fail;
}
for (i = 0; i < 3; i++) {
if (!(arg = consume_arg(&bp, &end))) {
FMT_ERR("Facet with < 3 args!\n");
- goto format_error;
+ goto fail;
}
farg = strtof(arg, &tmp);
if (!isws(*tmp)) {
FMT_ERR("Facet arg '%s'\n", arg);
- goto format_error;
+ goto fail;
}
}
break;
@@ -198,19 +198,19 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
if ((kw = stack_pop(&states)) != STATE_FACET) {
FMT_ERR("Improper nesting, parent: %s\n",
kwmap[kw].str);
- goto format_error;
+ goto fail;
}
break;
case KW_VERTEX:
for (i = 0; i < 3; i++) {
if (!(arg = consume_arg(&bp, &end))) {
FMT_ERR("Vertex with < 3 args\n");
- goto format_error;
+ goto fail;
}
farg = strtof(arg, &tmp);
if (!isws(*tmp)) {
FMT_ERR("Vertex arg '%s'\n", arg);
- goto format_error;
+ goto fail;
}
info->bbmin[i] = MIN(info->bbmin[i], farg);
info->bbmax[i] = MAX(info->bbmax[i], farg);
@@ -219,26 +219,26 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len)
case KW_UNKNOWN:
prev = skipws(prev);
FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, prev);
- goto format_error;
+ goto fail;
}
prev = bp;
}
if (states.count) {
FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, bp);
- goto format_error;
+ goto fail;
}
bp = skipws(bp);
if (*bp) {
FMT_ERR("Extraneous data at end of file\n");
- goto format_error;
+ goto fail;
}
stack_free(&states);
return OK;
-format_error:
+fail:
stack_free(&states);
return FAIL;
}
@@ -305,7 +305,7 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len)
return OK;
fail:
- NFREE(info->solidname);
+ FREE(info->solidname);
return FAIL;
}
@@ -316,7 +316,8 @@ parse_file(struct parseinfo *info, char *buf, size_t len)
const char *resp;
char *bp;
- free_info(info);
+ if (info->valid)
+ free_info(info);
if (len < 10) {
ERR("File too small!\n");
@@ -332,8 +333,6 @@ parse_file(struct parseinfo *info, char *buf, size_t len)
: parse_file_bin(info, buf, len);
if (status == FAIL) return FAIL;
- if (!info->solidname) info->solidname = checkp(strdup(""));
-
if (!info->modelname) {
resp = ask("Please enter your model name: ");
if (strlen(resp) < 4) {
@@ -343,6 +342,8 @@ parse_file(struct parseinfo *info, char *buf, size_t len)
info->modelname = checkp(strdup(resp));
}
+ if (!info->solidname) info->solidname = checkp(strdup(""));
+
info->hash = checkp(strdup(mhash(info->modelname, -1)));
return OK;
@@ -407,12 +408,9 @@ print_info(struct parseinfo *info)
{
int i, k;
-#define FILTERCHAR(c) ((c) >= 32 ? (c) : ' ')
-
printf(" === Model info === \n");
printf(" File Size: %u\n", info->filesize);
-
if (info->type == TYPE_BIN) {
printf(" Header:\n");
for (i = 0; i < 80; i += k) {
@@ -421,11 +419,10 @@ print_info(struct parseinfo *info)
printf(" %02x", (uint8_t) info->header[i+k]);
printf(" | ");
for (k = 0; k < MIN(80 - i, 20); k++)
- printf("%c", FILTERCHAR(info->header[i+k]));
+ putchar(PRINTABLE(info->header[i+k]));
printf("\n");
}
}
-
printf(" Model ID: %s\n", info->hash);
printf(" Model Name: %s\n", info->modelname);
printf(" Solid Name: %s\n", info->solidname);
@@ -443,9 +440,9 @@ print_info(struct parseinfo *info)
void
free_info(struct parseinfo *info)
{
- NFREE(info->hash);
- NFREE(info->modelname);
- NFREE(info->solidname);
+ FREE(info->hash);
+ FREE(info->modelname);
+ FREE(info->solidname);
info->valid = 0;
}
diff --git a/src/util.h b/src/util.h
@@ -11,10 +11,12 @@
#define MIN(x,y) ((x) > (y) ? (y) : (x))
#define MAX(x,y) ((x) < (y) ? (y) : (x))
+#define PRINTABLE(c) ((c) >= 32 ? (c) : ' ')
+
#define ERR(...) fprintf(stderr, "ERR: " __VA_ARGS__)
-#define NFREE(p) do { free(p); p = NULL; } while (0)
-#define NFCLOSE(f) do { fclose(f); f = NULL; } while (0)
+#define FREE(p) do { free(p); p = NULL; } while (0)
+#define FCLOSE(f) do { if (f) fclose(f); f = NULL; } while (0)
#define MHASHLEN 40