Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GCC 7.1 fixes #6253

Merged
merged 1 commit into from
Jun 28, 2017
Merged

GCC 7.1 fixes #6253

merged 1 commit into from
Jun 28, 2017

Conversation

tonyhutter
Copy link
Contributor

@tonyhutter tonyhutter commented Jun 20, 2017

GCC 7.1 with will warn when we're not checking the snprintf()
return code in cases where the buffer could be truncated. This
patch either checks the snprintf return code (where applicable),
or simply disables the warnings (ztest.c).

Signed-off-by: Tony Hutter hutter2@llnl.gov

Motivation and Context

Fixes #6221

How Has This Been Tested?

Built on Fedora 26 alpha with gcc 7.1.1

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation (a change to man pages or other documentation)

Checklist:

  • My code follows the ZFS on Linux code style requirements.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • All commit messages are properly formatted and contain Signed-off-by.
  • Change has been approved by a ZFS on Linux member.

@tonyhutter tonyhutter added the Type: Building Indicates an issue related to building binaries label Jun 20, 2017
Copy link
Contributor

@dinatale2 dinatale2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be an oversimplification, but couldn't you provide a #define TRUNC(func) if (func) {; } then all your snprintf calls can become something like TRUNC(snprintf(....));. Thoughts?

GCC 7.1 with will warn when we're not checking the snprintf()
return code in cases where the buffer could be truncated. This
patch either checks the snprintf return code (where applicable),
or simply disables the warnings (ztest.c).

Signed-off-by: Tony Hutter <hutter2@llnl.gov>
@tonyhutter
Copy link
Contributor Author

@dinatale2 unfortunately I get the same build errors with that since the gcc still knows the size at compile time. This hack seems to work though:

#define SNPRINTF_TRUNC(str, size, ...) {volatile int s = size; if (snprintf(str, s, __VA_ARGS__)) {; }}

I've updated the code with this in my latest push.

@tonyhutter
Copy link
Contributor Author

Looks like I don't need the if() in SNPRINTF_TRUNC anymore - removed in latest push.

char *__buf = alloca(256); \
(void) snprintf(__buf, 256, \
char *__buf = NULL; \
int rc = asprintf(&__buf, \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asprintf will require a free. But I don't see why we need to do this. Why not pass the format strings and variable all the way, or pass va_list?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other four callers of libspl_assert() just pass it a const string, so it makes sense to have VERIFY3_IMPL pass in a string as well (rather than a format string + vars).

I'll get rid of the asprintf and use a "snprintf to get size + alloca(size)" to allocate __buf.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then how about adding a libspl_assertf?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me

*/
#define SNPRINTF_TRUNC(str, size, ...) { \
volatile int s = size; \
snprintf(str, s, __VA_ARGS__); \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be ##__VA_ARGS__ to allow zero arguments.
Also, wrap this in do { } while (0)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, will fix

Copy link
Contributor

@tuxoko tuxoko Jun 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose for the volatile?
Shouldn't it be fine if you pass in size directly, as it's only used once?

Copy link
Contributor Author

@tonyhutter tonyhutter Jun 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

volatile fools gcc into not computing the buffer size at compile time, and thus prevents the compiler warning about snprintf truncation.

va_list args;
va_start(args, format);
size = vsnprintf(NULL, 0, format, args);
buf = alloca(size + 1);
Copy link
Contributor

@tuxoko tuxoko Jun 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant was feed the format string directly to fprintf, so we don't need to allocate any thing.
Edit, or I should say vfprintf.

* able to compute the truncation at compile time, and thus no error.
*/
#define SNPRINTF_TRUNC(str, size, ...) do { \
volatile int s = size; \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is required then you should change it to __s to prevent name collision.

@tonyhutter
Copy link
Contributor Author

@tuxoko my latest push should have all the fixes you were looking for

#define SNPRINTF_TRUNC(str, size, ...) do { \
volatile int __s = size; \
snprintf(str, __s, ##__VA_ARGS__); \
} while (0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the single exception in zvol.c it looks like SNPRINTF_TRUNC is only needed by ztest.c. In order to avoid tempting developers to use the wrapper in the core ZFS code, where there needs to be proper error handling and we want gcc to warn us, let's move this macro in to ztest.c. The usage in zvol_rename_minors_impl() can be fixed by using kmem_asprintf() to always dynamically allocate a long enough buffer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And with the only semi-legitimate usage of this now occurring in ztest.c we should be able to eliminate the need for this macro entirely by building ztest with -Wnoformat-truncation. Here's an untested patch, you may need to structure this like the ZFS_AC_CONFIG_USER_FRAME_LARGER_THAN to ensure the version of gcc being used supports the option. Alternately a pragma could be used for this.

diff --git a/cmd/ztest/Makefile.am b/cmd/ztest/Makefile.am
index a2f3b5a..c7ac681 100644
--- a/cmd/ztest/Makefile.am
+++ b/cmd/ztest/Makefile.am
@@ -1,6 +1,6 @@
 include $(top_srcdir)/config/Rules.am
 
-AM_CFLAGS += $(DEBUG_STACKFLAGS) $(FRAME_LARGER_THAN)
+AM_CFLAGS += $(DEBUG_STACKFLAGS) $(FRAME_LARGER_THAN) -Wnoformat-truncation
 AM_CPPFLAGS += -DDEBUG
 
 DEFAULT_INCLUDES += \

@tonyhutter
Copy link
Contributor Author

@behlendorf all comments fixed in latest push

@tonyhutter
Copy link
Contributor Author

Updated commit message to remove the mention of snprintf_trunc

])

CFLAGS="$saved_flags"
AC_SUBST([NO_FORMAT_TRUNCATION])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ctyle: spaces instead of tabs

@@ -2086,16 +2085,18 @@ zvol_rename_minors_impl(const char *oldname, const char *newname)
} else if (strncmp(zv->zv_name, oldname, oldnamelen) == 0 &&
(zv->zv_name[oldnamelen] == '/' ||
zv->zv_name[oldnamelen] == '@')) {
snprintf(name, MAXNAMELEN, "%s%c%s", newname,
name = kmem_asprintf("%s%c%s", newname,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: kmem_asprintf() using KM_SLEEP internally and cannot fail so we can drop the if (name != NULL) checks. What do you think about the following to simplify this.

diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index 8890aaa..21d4467 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -2063,14 +2063,12 @@ zvol_rename_minors_impl(const char *oldname, const char 
 {
        zvol_state_t *zv, *zv_next;
        int oldnamelen, newnamelen;
-       char *name;
 
        if (zvol_inhibit_dev)
                return;
 
        oldnamelen = strlen(oldname);
        newnamelen = strlen(newname);
-       name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 
        mutex_enter(&zvol_state_lock);
 
@@ -2086,16 +2084,15 @@ zvol_rename_minors_impl(const char *oldname, const char 
                } else if (strncmp(zv->zv_name, oldname, oldnamelen) == 0 &&
                    (zv->zv_name[oldnamelen] == '/' ||
                    zv->zv_name[oldnamelen] == '@')) {
-                       snprintf(name, MAXNAMELEN, "%s%c%s", newname,
+                       char *name = kmem_asprintf("%s%c%s", newname,
                            zv->zv_name[oldnamelen],
                            zv->zv_name + oldnamelen + 1);
                        zvol_rename_minor(zv, name);
+                       kmem_free(name, strlen(name + 1));
                }
        }
 
        mutex_exit(&zvol_state_lock);
-
-       kmem_free(name, MAXNAMELEN);
 }
 
 typedef struct zvol_snapdev_cb_arg {

if (snprintf(namebuf, sizeof (namebuf), "%s/%s",
zc->zc_name, recv_clone_name) >=
sizeof (namebuf))
return (EINVAL);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: return (SET_ERROR(EINVAL));.

@tonyhutter tonyhutter force-pushed the gcc7-fix branch 2 times, most recently from 1425695 to 0f8523d Compare June 27, 2017 17:39
Copy link
Contributor

@behlendorf behlendorf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last thing!

@@ -0,0 +1,22 @@
dnl #
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should be renamed user-no-format-truncation.m4 since the configure check is only run as part of the user space build.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, will rename

@tonyhutter
Copy link
Contributor Author

@behlendorf file renamed in latest push

@behlendorf behlendorf merged commit 682ce10 into openzfs:master Jun 28, 2017
tonyhutter added a commit to tonyhutter/zfs that referenced this pull request Jun 29, 2017
GCC 7.1 with will warn when we're not checking the snprintf()
return code in cases where the buffer could be truncated. This
patch either checks the snprintf return code (where applicable),
or simply disables the warnings (ztest.c).

Reviewed-by: Chunwei Chen <david.chen@osnexus.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes openzfs#6253
tonyhutter added a commit that referenced this pull request Jul 20, 2017
GCC 7.1 with will warn when we're not checking the snprintf()
return code in cases where the buffer could be truncated. This
patch either checks the snprintf return code (where applicable),
or simply disables the warnings (ztest.c).

Reviewed-by: Chunwei Chen <david.chen@osnexus.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes #6253
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Building Indicates an issue related to building binaries
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ZFS doesn't build on Fedora 26 alpha
4 participants