From: Alberto Leiva Popper Date: Thu, 3 Feb 2022 21:43:27 +0000 (-0600) Subject: File: Patch undefined behavior X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e1dc802ec8b31f9f48c8cd88a74993e675b1e35d;p=thirdparty%2FFORT-validator.git File: Patch undefined behavior Code was falling into the `strchr()` trap: last_slash = strrchr(path, '/'); *last_slash = '\0'; `path` is const, and `strrchr()` returns a pointer to the same string, so the second line was risking a const edit. Also fixes some leftover compilation problems. --- diff --git a/src/file.c b/src/file.c index cdf7e80a..8cfbfe4a 100644 --- a/src/file.c +++ b/src/file.c @@ -300,13 +300,24 @@ valid_file_or_dir(char const *location, bool check_file, bool check_dir, } static int -dir_exists(char const *path, bool *result) +dir_exists(char const *_path, bool *result) { - struct stat _stat; + char *path; char *last_slash; + struct stat _stat; + int error; + + /* + * Need to remove the const, otherwise "= '\0'" below causes undefined + * behavior. + */ + path = strdup(_path); + if (path == NULL) + return pr_enomem(); last_slash = strrchr(path, '/'); if (last_slash == NULL) { + free(path); /* * Simply because create_dir_recursive() has nothing meaningful * to do when this happens. It's a pretty strange error. @@ -319,17 +330,21 @@ dir_exists(char const *path, bool *result) if (stat(path, &_stat) == 0) { if (!S_ISDIR(_stat.st_mode)) { - return pr_op_err("Path '%s' exists and is not a directory.", + error = pr_op_err("Path '%s' exists and is not a directory.", path); + free(path); + return error; } *result = true; } else if (errno == ENOENT) { *result = false; } else { - return pr_op_errno(errno, "stat() failed"); + error = errno; + free(path); + return pr_op_errno(error, "stat() failed"); } - *last_slash = '/'; + free(path); return 0; } diff --git a/src/http/http.c b/src/http/http.c index ad4e6c64..f8438518 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -352,7 +352,7 @@ retry_until_done(char const *remote, char const *local, long ims) * Return values: * * - 0: Download successful. - * - ENOTCHANGED: File hasn't changed since `args->ims`. + * - ENOTCHANGED: File hasn't changed since @ims. * - < 0: Something went wrong. */ int diff --git a/src/rrdp/delta.c b/src/rrdp/delta.c index 27c78542..053dafa4 100644 --- a/src/rrdp/delta.c +++ b/src/rrdp/delta.c @@ -71,7 +71,7 @@ xml_read_delta(xmlTextReaderPtr reader, void *arg) name = xmlTextReaderConstLocalName(reader); if (xmlStrEqual(name, PUBLISH)) - return handle_publish_tag(reader, true, ctx->notification); + return handle_publish_tag(reader, ctx->notification, true); if (xmlStrEqual(name, WITHDRAW)) return handle_withdraw_tag(reader, ctx->notification); if (xmlStrEqual(name, DELTA)) { diff --git a/src/rrdp/snapshot.c b/src/rrdp/snapshot.c index 5ee1290c..9adeb2c6 100644 --- a/src/rrdp/snapshot.c +++ b/src/rrdp/snapshot.c @@ -1,6 +1,7 @@ #include "rrdp/snapshot.h" #define _XOPEN_SOURCE 500 +#define __USE_XOPEN_EXTENDED 1 #include #include "thread_var.h" @@ -29,7 +30,7 @@ clear_caged_directory(struct rrdp_notification *notif) struct rpki_uri *cage; int error; - error = uri_create_caged(NULL, notif, &cage); + error = uri_create_caged(NULL, notif->uri, &cage); if (error) return error; diff --git a/src/rrdp/types.c b/src/rrdp/types.c index e0f208d7..c4007639 100644 --- a/src/rrdp/types.c +++ b/src/rrdp/types.c @@ -422,14 +422,9 @@ write_from_uri(struct rrdp_publish *publish) file = uri_get_local(publish->target.uri); - /* - * TODO (aaaa) shouldn't this be reverted on error? - * Also, shouldn't create_dir_recursive() be inside file_write()? - */ error = create_dir_recursive(file); if (error) return error; - error = file_write(file, &out); if (error) return error; @@ -439,6 +434,7 @@ write_from_uri(struct rrdp_publish *publish) file_close(out); + /* fwrite does not yield an error message... */ if (written != (sizeof(unsigned char) * publish->content_len)) return pr_val_err("Couldn't write bytes to file '%s'", file); diff --git a/src/rrdp/types.h b/src/rrdp/types.h index b4748084..46cb3ced 100644 --- a/src/rrdp/types.h +++ b/src/rrdp/types.h @@ -54,6 +54,6 @@ int parse_hash_attribute(xmlTextReaderPtr, bool, struct rrdp_file_metadata *); int parse_header_tag(xmlTextReaderPtr, struct rrdp_session *); int validate_header_tag(xmlTextReaderPtr, struct rrdp_session *); -int handle_publish_tag(xmlTextReaderPtr, struct rrdp_notification *); +int handle_publish_tag(xmlTextReaderPtr, struct rrdp_notification *, bool); #endif /* SRC_RRDP_TYPES_H_ */