Richard W.M. Jones
2017-Feb-14 15:02 UTC
[Libguestfs] [PATCH 1/2] GCC 7: Add __attribute__((noreturn)) to some usage functions which call exit.
This happens with GCC 7.0.1. The errors were all of the form: qemu-speed-test.c: In function 'main': qemu-speed-test.c:153:7: error: this statement may fall through [-Werror=implicit-fallthrough=] usage (EXIT_SUCCESS); ^~~~~~~~~~~~~~~~~~~~ qemu-speed-test.c:155:5: note: here default: ^~~~~~~ --- builder/index-validate.c | 2 +- utils/boot-analysis/boot-analysis.c | 2 +- utils/boot-benchmark/boot-benchmark.c | 2 +- utils/qemu-boot/qemu-boot.c | 2 +- utils/qemu-speed-test/qemu-speed-test.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/builder/index-validate.c b/builder/index-validate.c index d3912f3..33086b2 100644 --- a/builder/index-validate.c +++ b/builder/index-validate.c @@ -38,7 +38,7 @@ extern int do_parse (struct parse_context *context, FILE *in); -static void +static void __attribute__((noreturn)) usage (int exit_status) { printf ("%s index\n", getprogname ()); diff --git a/utils/boot-analysis/boot-analysis.c b/utils/boot-analysis/boot-analysis.c index 04b3bdd..1bec9a5 100644 --- a/utils/boot-analysis/boot-analysis.c +++ b/utils/boot-analysis/boot-analysis.c @@ -88,7 +88,7 @@ static void print_longest_to_shortest (void); static void free_pass_data (void); static void free_final_timeline (void); -static void +static void __attribute__((noreturn)) usage (int exitcode) { guestfs_h *g; diff --git a/utils/boot-benchmark/boot-benchmark.c b/utils/boot-benchmark/boot-benchmark.c index 73da722..4af3943 100644 --- a/utils/boot-benchmark/boot-benchmark.c +++ b/utils/boot-benchmark/boot-benchmark.c @@ -51,7 +51,7 @@ static void run_test (void); static guestfs_h *create_handle (void); static void add_drive (guestfs_h *g); -static void +static void __attribute__((noreturn)) usage (int exitcode) { guestfs_h *g; diff --git a/utils/qemu-boot/qemu-boot.c b/utils/qemu-boot/qemu-boot.c index 1551a1a..6881835 100644 --- a/utils/qemu-boot/qemu-boot.c +++ b/utils/qemu-boot/qemu-boot.c @@ -74,7 +74,7 @@ static void run_test (size_t P); static void *start_thread (void *thread_data_vp); static void message_callback (guestfs_h *g, void *opaque, uint64_t event, int event_handle, int flags, const char *buf, size_t buf_len, const uint64_t *array, size_t array_len); -static void +static void __attribute__((noreturn)) usage (int exitcode) { fprintf (stderr, diff --git a/utils/qemu-speed-test/qemu-speed-test.c b/utils/qemu-speed-test/qemu-speed-test.c index 54875fa..5aa663c 100644 --- a/utils/qemu-speed-test/qemu-speed-test.c +++ b/utils/qemu-speed-test/qemu-speed-test.c @@ -66,7 +66,7 @@ reset_default_tests (int *flag) } } -static void +static void __attribute__((noreturn)) usage (int exitcode) { fprintf (stderr, -- 2.10.2
Richard W.M. Jones
2017-Feb-14 15:02 UTC
[Libguestfs] [PATCH 2/2] GCC 7: Allocate sufficient space for sprintf output.
GCC 7.0.1 can determine if there is likely to be sufficient space in the output buffer when using sprintf/snprintf, based on the format string. The errors were all either of this form: bindtests.c:717:29: error: '%zu' directive output may be truncated writing between 1 and 19 bytes into a region of size 16 [-Werror=format-truncation=] snprintf (strs[i], 16, "%zu", i); ^~~ bindtests.c:717:28: note: directive argument in the range [0, 2305843009213693951] snprintf (strs[i], 16, "%zu", i); ^~~~~ or this form: sync.c: In function 'fsync_devices': sync.c:108:50: error: '%s' directive output may be truncated writing up to 255 bytes into a region of size 251 [-Werror=format-truncation=] snprintf (dev_path, sizeof dev_path, "/dev/%s", d->d_name); ^~ Fixed by converting these into dynamic allocation, or making the output buffer larger, whichever was easier. --- cat/filesystems.c | 2 +- daemon/9p.c | 10 +++++++--- daemon/debug.c | 12 ++++++++++-- daemon/devsparts.c | 16 ++++++++++++---- daemon/sync.c | 7 +++++-- generator/bindtests.ml | 12 ++++++------ 6 files changed, 41 insertions(+), 18 deletions(-) diff --git a/cat/filesystems.c b/cat/filesystems.c index 1036c6f..4264b0f 100644 --- a/cat/filesystems.c +++ b/cat/filesystems.c @@ -866,7 +866,7 @@ write_row (const char *name, const char *type, size_t len = 0; char hum[LONGEST_HUMAN_READABLE]; char num[256]; - char mbr_id_str[3]; + char mbr_id_str[9]; if ((columns & COLUMN_NAME)) strings[len++] = name; diff --git a/daemon/9p.c b/daemon/9p.c index a9e36d1..f72c8dd 100644 --- a/daemon/9p.c +++ b/daemon/9p.c @@ -71,9 +71,13 @@ do_list_9p (void) if (d == NULL) break; if (STRPREFIX (d->d_name, "virtio")) { - char mount_tag_path[256]; - snprintf (mount_tag_path, sizeof mount_tag_path, - BUS_PATH "/%s/mount_tag", d->d_name); + CLEANUP_FREE char *mount_tag_path; + if (asprintf (&mount_tag_path, BUS_PATH "/%s/mount_tag", + d->d_name) == -1) { + reply_with_perror ("asprintf"); + closedir (dir); + return NULL; + } /* A bit unclear, but it looks like the virtio transport allows * the mount tag length to be unlimited (or up to 65536 bytes). diff --git a/daemon/debug.c b/daemon/debug.c index 06f0729..b18d87c 100644 --- a/daemon/debug.c +++ b/daemon/debug.c @@ -161,7 +161,7 @@ debug_fds (const char *subcmd, size_t argc, char *const *const argv) FILE *fp; DIR *dir; struct dirent *d; - char fname[256], link[256]; + char link[256]; struct stat statbuf; fp = open_memstream (&out, &size); @@ -178,10 +178,18 @@ debug_fds (const char *subcmd, size_t argc, char *const *const argv) } while ((d = readdir (dir)) != NULL) { + CLEANUP_FREE char *fname = NULL; + if (STREQ (d->d_name, ".") || STREQ (d->d_name, "..")) continue; - snprintf (fname, sizeof fname, "/proc/self/fd/%s", d->d_name); + if (asprintf (&fname, "/proc/self/fd/%s", d->d_name) == -1) { + reply_with_perror ("asprintf"); + fclose (fp); + free (out); + closedir (dir); + return NULL; + } r = lstat (fname, &statbuf); if (r == -1) { diff --git a/daemon/devsparts.c b/daemon/devsparts.c index f15d2c3..96e867f 100644 --- a/daemon/devsparts.c +++ b/daemon/devsparts.c @@ -43,7 +43,6 @@ foreach_block_device (block_dev_func_t func, bool return_md) DIR *dir; int err = 0; struct dirent *d; - char dev_path[256]; int fd; dir = opendir ("/sys/block"); @@ -64,7 +63,12 @@ foreach_block_device (block_dev_func_t func, bool return_md) STREQLEN (d->d_name, "sr", 2) || (return_md && STREQLEN (d->d_name, "md", 2) && c_isdigit (d->d_name[2]))) { - snprintf (dev_path, sizeof dev_path, "/dev/%s", d->d_name); + CLEANUP_FREE char *dev_path; + if (asprintf (&dev_path, "/dev/%s", d->d_name) == -1) { + reply_with_perror ("asprintf"); + closedir (dir); + return NULL; + } /* Ignore the root device. */ if (is_root_device (dev_path)) @@ -167,8 +171,12 @@ add_partitions (const char *device, struct stringsbuf *r) struct dirent *d; while ((d = readdir (dir)) != NULL) { if (STREQLEN (d->d_name, device, strlen (device))) { - char part[256]; - snprintf (part, sizeof part, "/dev/%s", d->d_name); + CLEANUP_FREE char *part; + if (asprintf (&part, "/dev/%s", d->d_name) == -1) { + perror ("asprintf"); + closedir (dir); + return -1; + } if (add_string (r, part) == -1) { closedir (dir); diff --git a/daemon/sync.c b/daemon/sync.c index 581fa0f..b64f6e3 100644 --- a/daemon/sync.c +++ b/daemon/sync.c @@ -86,7 +86,6 @@ fsync_devices (void) { DIR *dir; struct dirent *d; - char dev_path[256]; int fd; dir = opendir ("/sys/block"); @@ -105,7 +104,11 @@ fsync_devices (void) STREQLEN (d->d_name, "ubd", 3) || STREQLEN (d->d_name, "vd", 2) || STREQLEN (d->d_name, "sr", 2)) { - snprintf (dev_path, sizeof dev_path, "/dev/%s", d->d_name); + CLEANUP_FREE char *dev_path; + if (asprintf (&dev_path, "/dev/%s", d->d_name) == -1) { + perror ("asprintf"); + continue; + } /* Ignore the root device. */ if (is_root_device (dev_path)) diff --git a/generator/bindtests.ml b/generator/bindtests.ml index 22d0c37..2fde425 100644 --- a/generator/bindtests.ml +++ b/generator/bindtests.ml @@ -258,8 +258,8 @@ fill_lvm_pv (guestfs_h *g, struct guestfs_lvm_pv *pv, size_t i) pr " }\n"; pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n"; pr " for (i = 0; i < n; ++i) {\n"; - pr " strs[i] = safe_malloc (g, 16);\n"; - pr " snprintf (strs[i], 16, \"%%zu\", i);\n"; + pr " strs[i] = safe_malloc (g, 20);\n"; + pr " snprintf (strs[i], 20, \"%%zu\", i);\n"; pr " }\n"; pr " strs[n] = NULL;\n"; pr " return strs;\n" @@ -290,10 +290,10 @@ fill_lvm_pv (guestfs_h *g, struct guestfs_lvm_pv *pv, size_t i) pr " }\n"; pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n"; pr " for (i = 0; i < n; ++i) {\n"; - pr " strs[i*2] = safe_malloc (g, 16);\n"; - pr " strs[i*2+1] = safe_malloc (g, 16);\n"; - pr " snprintf (strs[i*2], 16, \"%%zu\", i);\n"; - pr " snprintf (strs[i*2+1], 16, \"%%zu\", i);\n"; + pr " strs[i*2] = safe_malloc (g, 20);\n"; + pr " strs[i*2+1] = safe_malloc (g, 20);\n"; + pr " snprintf (strs[i*2], 20, \"%%zu\", i);\n"; + pr " snprintf (strs[i*2+1], 20, \"%%zu\", i);\n"; pr " }\n"; pr " strs[n*2] = NULL;\n"; pr " return strs;\n" -- 2.10.2
Daniel P. Berrange
2017-Feb-14 15:14 UTC
Re: [Libguestfs] [PATCH 2/2] GCC 7: Allocate sufficient space for sprintf output.
On Tue, Feb 14, 2017 at 03:02:14PM +0000, Richard W.M. Jones wrote:> GCC 7.0.1 can determine if there is likely to be sufficient space in > the output buffer when using sprintf/snprintf, based on the format > string. > > The errors were all either of this form: > > bindtests.c:717:29: error: '%zu' directive output may be truncated writing between 1 and 19 bytes into a region of size 16 [-Werror=format-truncation=] > snprintf (strs[i], 16, "%zu", i); > ^~~ > bindtests.c:717:28: note: directive argument in the range [0, 2305843009213693951] > snprintf (strs[i], 16, "%zu", i); > ^~~~~ > > or this form: > > sync.c: In function 'fsync_devices': > sync.c:108:50: error: '%s' directive output may be truncated writing up to 255 bytes into a region of size 251 [-Werror=format-truncation=] > snprintf (dev_path, sizeof dev_path, "/dev/%s", d->d_name); > ^~ > > Fixed by converting these into dynamic allocation, or making the > output buffer larger, whichever was easier. > --- > cat/filesystems.c | 2 +- > daemon/9p.c | 10 +++++++--- > daemon/debug.c | 12 ++++++++++-- > daemon/devsparts.c | 16 ++++++++++++---- > daemon/sync.c | 7 +++++-- > generator/bindtests.ml | 12 ++++++------ > 6 files changed, 41 insertions(+), 18 deletions(-) > > diff --git a/cat/filesystems.c b/cat/filesystems.c > index 1036c6f..4264b0f 100644 > --- a/cat/filesystems.c > +++ b/cat/filesystems.c > @@ -866,7 +866,7 @@ write_row (const char *name, const char *type, > size_t len = 0; > char hum[LONGEST_HUMAN_READABLE]; > char num[256]; > - char mbr_id_str[3]; > + char mbr_id_str[9];[snip]> @@ -258,8 +258,8 @@ fill_lvm_pv (guestfs_h *g, struct guestfs_lvm_pv *pv, size_t i) > pr " }\n"; > pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n"; > pr " for (i = 0; i < n; ++i) {\n"; > - pr " strs[i] = safe_malloc (g, 16);\n"; > - pr " snprintf (strs[i], 16, \"%%zu\", i);\n"; > + pr " strs[i] = safe_malloc (g, 20);\n"; > + pr " snprintf (strs[i], 20, \"%%zu\", i);\n"; > pr " }\n"; > pr " strs[n] = NULL;\n"; > pr " return strs;\n" > @@ -290,10 +290,10 @@ fill_lvm_pv (guestfs_h *g, struct guestfs_lvm_pv *pv, size_t i) > pr " }\n"; > pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n"; > pr " for (i = 0; i < n; ++i) {\n"; > - pr " strs[i*2] = safe_malloc (g, 16);\n"; > - pr " strs[i*2+1] = safe_malloc (g, 16);\n"; > - pr " snprintf (strs[i*2], 16, \"%%zu\", i);\n"; > - pr " snprintf (strs[i*2+1], 16, \"%%zu\", i);\n"; > + pr " strs[i*2] = safe_malloc (g, 20);\n"; > + pr " strs[i*2+1] = safe_malloc (g, 20);\n"; > + pr " snprintf (strs[i*2], 20, \"%%zu\", i);\n"; > + pr " snprintf (strs[i*2+1], 20, \"%%zu\", i);\n"; > pr " }\n"; > pr " strs[n*2] = NULL;\n"; > pr " return strs;\n"FWIW, for cases where you really do want to print an integer into a fixed length buffer, then gnulib has a useful macro to let you automatically determine the correct buffer size at compile time. size_t someval; char buf[INT_BUFSIZE_BOUND(someval)] snprintf(buf, ARRAY_CARDINALITY(buf), "%zu", someval) Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://entangle-photo.org -o- http://search.cpan.org/~danberr/ :|
Apparently Analagous Threads
- [PATCH v2 0/2] GCC 7: Misc fixes
- [PATCH 2/2] GCC 7: Allocate sufficient space for sprintf output.
- [PATCH v2 2/2] GCC 7: Allocate sufficient space for sprintf output.
- [PATCH 1/2] daemon: Fix part-to-dev when the partition name includes p<N>.
- [PATCH 0/7 v2] Fix and workaround for qcow2 issues in qemu causing data corruption.