linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Linux List Kernel Mailing <linux-kernel@vger.kernel.org>,
	Ingo Molnar <mingo@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Namhyung Kim <namhyung@kernel.org>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	Joe Perches <joe@perches.com>, Tom Zanussi <zanussi@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: Re: [for-next][PATCH 23/24] string.h: Add strncmp_prefix() helper macro
Date: Fri, 21 Dec 2018 14:40:54 -0500	[thread overview]
Message-ID: <20181221144054.20bdeb33@gandalf.local.home> (raw)
In-Reply-To: <CAHk-=wg_sR-UEC1ggmkZpypOUYanL5CMX4R7ceuaV4QMf5jBtg@mail.gmail.com>

On Fri, 21 Dec 2018 10:51:29 -0800
Linus Torvalds <torvalds@linux-foundation.org> wrote:

> On Fri, Dec 21, 2018 at 9:57 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> >
> > I figured the best thing to do is to create a helper macro and place it
> > into include/linux/string.h. And go around and fix all the open coded
> > versions of it later.
> >
> > I plan on only applying this patch and updating the tracing hooks for
> > this merge window. And perhaps use it to fix some of the bugs that were
> > found.  
> 
> I like the helper function concept, but as they say about CS: "There
> is only one hard problem in computer science: naming and off-by-one
> errors".
> 
> And this one has that problem. The name makes absolutely no sense.

Good thing I rebased and put these patches at the end before running
my tests :-) (Specifically because I was expecting to have feedback like
this).

> 
> Calling it "strncmp_prefix()" when there is no "n" there makes no sense.
> 
> So drop the "n" from the name.

I originally did that, but then I thought strcmp() is a full compare,
and 'n' denotes it is partial. But thinking about it more, yeah one
would think it would need a parameter to represent 'n'.

> 
> And honestly, maybe it would be better to use a different naming
> pattern entirely, and avoid the crazy non-boolean "str*cmp()" model.
> That thing is useful for search comparisons (where "before/after"
> matters), but it's horrible for the actual "is this true or not",
> where the code ends up being
> 
>         if (!strcmp_prefix(a, "prefix")) {
>                 // This is the "Yes, prefix matched" case, despite the
> "if !" syntax
> 
> which is just confusing.
> 
> So I'd really prefer more of a
> 
>         #define has_prefix(str, prefix) ...

I like changing the name.

> 
> model that actually returns a boolean (true if it has a prefix, false
> if it doesn't), rather than use the "str*cmp" naming and return
> values.

Actually, instead of returning a bool, it can return the length if it
matches.

Reason being, there's several locations that does something like:

	while (...) {
		len = strlen("const");
		if (strncmp(str, "const", len) == 0) {
			str += len;
			break;
		}
	}

And I was having trouble thinking about how to deal with these. But if
we have a has_prefix() that returns the length on match then we can do:

	if ((len = has_prefix(str, "const")) {
		str += len;



> 
> (But I agree that *if* you use the "strcmp" naming, then you do need
> to hold to the traditional strcmp return value semantics).
> 
> Hmm?
> 
> Finally, I also suspect that your helper might be slightly fragile.
> Doing sizeof() seems broken. I could see somebody using some prefix
> define for arrays with constant sizes, and doing
> 
>    #define PFX1 "cpp\0"
>    #define PFX2 "c\0\0\0"
>    #define PFX3 "h\0\0\0"
> 
> or similar. Also, is there a reason you use "&prefix" for the constant

That was left over in my original tests in userspace. When I first
tried it with __builtin_constant_p() I got an error, and added the '&',
but then fixed something else. The something else was what actually
caused the error, but since it didn't complain (and past all my tests),
I left in the '&'.

> test? I don't see that pattern anywhere else. Plus it looks entirely
> wrong without the parenthesis (ie "&(prefix)" to make sure we group
> things right).
> 
> So a lot of small problems, but the naming one is big.

OK, what about if we just use strlen() and say that this macro is not
safe for parameters with side effects.

-- Steve

diff --git a/include/linux/string.h b/include/linux/string.h
index 27d0482e5e05..f9d274a81276 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -14,6 +14,29 @@ extern void *memdup_user(const void __user *, size_t);
 extern void *vmemdup_user(const void __user *, size_t);
 extern void *memdup_user_nul(const void __user *, size_t);
 
+/**
+ * have_prefix - Test if a string has a given prefix
+ * @str: The string to test
+ * @prefix: The string to see if @str starts with
+ *
+ * IMPORTANT; @prefix must not have side effects (used more than once here)
+ *
+ * A common way to test a prefix of a string is to do:
+ *  strncmp(str, prefix, sizeof(prefix) - 1)
+ *
+ * But this can lead to bugs due to typos, or if prefix is a pointer
+ * and not a constant. Instead use has_prefix().
+ *
+ * Returns: 0 if @str does not start with @prefix
+         strlen(@prefix) if @str does start with @prefix
+ */
+#define has_prefix(str, prefix)						\
+	({								\
+		int ____strcmp_prefix_len____ = strlen(prefix);		\
+		strncmp(str, prefix, ____strcmp_prefix_len____) == 0 ?	\
+			____strcmp_prefix_len____ : 0;			\
+	})
+
 /*
  * Include machine specific inline routines
  */

  reply	other threads:[~2018-12-21 19:40 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-21 17:56 [for-next][PATCH 00/24] tracing: Updates for the next (coming soon) merge window Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 01/24] ftrace: Allow ftrace_replace_code() to be schedulable Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 02/24] arm64: ftrace: Set FTRACE_MAY_SLEEP before ftrace_modify_all_code() Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 03/24] fgraph: Add comment to describe ftrace_graph_get_ret_stack Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 04/24] x86/ftrace: Do not call function graph from dynamic trampolines Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 05/24] powerpc/frace: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack Steven Rostedt
2018-12-22  9:51   ` Michael Ellerman
2018-12-22 12:24     ` Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 06/24] sparc64: " Steven Rostedt
2018-12-21 18:24   ` David Miller
2018-12-21 19:29     ` Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 07/24] sh: ftrace: " Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 08/24] arm64: " Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 10/24] seq_buf: Use size_t for len in seq_buf_puts() Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 11/24] tracing: Fix ftrace_graph_get_ret_stack() to use task and not current Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 12/24] tracing: Remove unnecessary hist trigger struct field Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 13/24] tracing: Change strlen to sizeof for hist trigger static strings Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 14/24] tracing: Use var_refs[] for hist trigger reference checking Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 15/24] tracing: Remove open-coding of hist trigger var_ref management Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 16/24] tracing: Use hist triggers var_ref array to destroy var_refs Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 17/24] tracing: Remove hist trigger synth_var_refs Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 18/24] tracing: Add hist trigger comments for variable-related fields Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 19/24] tracing: Merge seq_print_sym_short() and seq_print_sym_offset() Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 21/24] tracing: Simplify printfing in seq_print_sym Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 23/24] string.h: Add strncmp_prefix() helper macro Steven Rostedt
2018-12-21 18:51   ` Linus Torvalds
2018-12-21 19:40     ` Steven Rostedt [this message]
2018-12-21 20:01       ` Linus Torvalds
2018-12-21 20:35         ` Steven Rostedt
2018-12-21 20:46           ` Joe Perches
2018-12-21 20:54             ` Steven Rostedt
2018-12-21 20:58               ` Andreas Schwab
2018-12-21 21:08                 ` Steven Rostedt
2018-12-21 22:20                   ` Joe Perches
2018-12-21 22:29                     ` Linus Torvalds
2018-12-21 22:58                       ` Steven Rostedt
2018-12-21 22:55                     ` Steven Rostedt
2018-12-23 22:01                     ` Rasmus Villemoes
2018-12-23 22:56                       ` Steven Rostedt
2018-12-23 23:52                         ` Rasmus Villemoes
2018-12-24  0:05                           ` Steven Rostedt
2018-12-23 23:01                       ` Joe Perches
2018-12-21 20:58             ` Steven Rostedt
     [not found]           ` <CAHk-=wjtkvFUuRNZU67KccuUKYHw=pYoDMQJ_9OVDFxOwmK9zQ@mail.gmail.com>
2018-12-21 20:55             ` Steven Rostedt
2018-12-21 22:08               ` Linus Torvalds
2018-12-21 22:48                 ` Steven Rostedt
2018-12-21 22:57                   ` Linus Torvalds
2018-12-21 23:03                     ` Steven Rostedt
2018-12-22 10:20     ` Malcolm Priestley
2018-12-22 12:26       ` Steven Rostedt
2018-12-21 17:56 ` [for-next][PATCH 24/24] tracing: Use strncmp_prefix() helper for histogram code Steven Rostedt
     [not found] ` <20181221175656.827708767@goodmis.org>
2018-12-21 18:00   ` [for-next][PATCH 09/24] seq_buf: Make seq_buf_puts() null-terminate the buffer Steven Rostedt
2018-12-21 18:05     ` Steven Rostedt
2018-12-27  5:25       ` Michael Ellerman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181221144054.20bdeb33@gandalf.local.home \
    --to=rostedt@goodmis.org \
    --cc=akpm@linux-foundation.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=joe@perches.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=zanussi@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).