Re: [PATCH 3/3] symbol.c: Set correct size of array from parenthesized string initializer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Chris Li wrote:
> On 05/20/2013 11:42 AM, Ramsay Jones wrote:
> 
>> Unfortunately not. :(
> 
> Sorry about that.
> 
>>         const char *paths[] = { path, NULL };
> 
> I see where I make the mistake. I need to drop the parentheses
> only for char type. Can you please try this patch again? It is a
> replacement patch of your patch No3. Not a delta. It works for the
> the test case above.
> 
> Let's hope this one works.

Yes, this patch works.

However, it made me go cross-eyed trying to follow the flow of
control. So, I created a new patch, added after the scissor mark
below, which hopefully makes the flow of control easier to follow.

Note that I originally wrote the code like:

    p = paren_string(expr);
    if (is_char && p)
        expr = p;

since sparse source seemed not to use assignments embedded into
conditions, but I stumbled across a few examples:

  $ git grep -n -e 'if (.*([a-zA-Z_]* = [a-zA-Z_]*'
  c2xml.c:173:            if ((base = builtin_typename(sym->ctype.base_type)) == N
  dissect.c:381:                  if ((expr = peek_preop(unop, '*')))
  dissect.c:388:                  if ((expr = peek_preop(unop, '&')))
  ptrlist.c:129:  if (!list || (nr = (last = list->prev)->nr) >= LIST_NODE_NR) {
  show-parse.c:289:       if ((typename = builtin_typename(sym))) {
  $

Also, note that I changed the test to add a check for the length
of the v1 array. Having said that, I had intended to rename the
variables in the test to u->y and a->e (this is a new test, after
all), but I forgot! sorry about that.

ATB,
Ramsay Jones

-- >8 --
From: Ramsay Jones <ramsay@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 8 Apr 2011 23:38:30 +0100
Subject: [PATCH] symbol.c: Set correct size of array from parenthesized string initializer


Signed-off-by: Ramsay Jones <ramsay@xxxxxxxxxxxxxxxxxxx>
---
 symbol.c                      | 22 ++++++++++++++++++++++
 validation/init-char-array1.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)
 create mode 100644 validation/init-char-array1.c

diff --git a/symbol.c b/symbol.c
index 80a2f23..55e1b47 100644
--- a/symbol.c
+++ b/symbol.c
@@ -269,8 +269,21 @@ void merge_type(struct symbol *sym, struct symbol *base_type)
 		merge_type(sym, sym->ctype.base_type);
 }
 
+static struct expression *paren_string(struct expression *expr)
+{
+	if (expr && expr->type == EXPR_PREOP && expr->op == '(') {
+		struct expression *e = expr;
+		while (e && e->type == EXPR_PREOP && e->op == '(')
+			e = e->unop;
+		if (e && e->type == EXPR_STRING)
+			return e;
+	}
+	return NULL;
+}
+
 static int count_array_initializer(struct symbol *t, struct expression *expr)
 {
+	struct expression *p;
 	int nr = 0;
 	int is_char = 0;
 
@@ -284,6 +297,10 @@ static int count_array_initializer(struct symbol *t, struct expression *expr)
 	if (t->ctype.base_type == &int_type && t->ctype.modifiers & MOD_CHAR)
 		is_char = 1;
 
+	/* check for a parenthesized string: char x[] = ("string"); */
+	if (is_char && (p = paren_string(expr)))
+		expr = p;
+
 	switch (expr->type) {
 	case EXPR_INITIALIZER: {
 		struct expression *entry;
@@ -296,6 +313,10 @@ static int count_array_initializer(struct symbol *t, struct expression *expr)
 				if (entry->idx_to >= nr)
 					nr = entry->idx_to+1;
 				break;
+			case EXPR_PREOP:
+				/* check for char x[] = {("string")}; */
+				if (is_char && (p = paren_string(entry)))
+					entry = p;
 			case EXPR_STRING:
 				if (is_char)
 					str_len = entry->string->length;
@@ -310,6 +331,7 @@ static int count_array_initializer(struct symbol *t, struct expression *expr)
 	case EXPR_STRING:
 		if (is_char)
 			nr = expr->string->length;
+		break;
 	default:
 		break;
 	}
diff --git a/validation/init-char-array1.c b/validation/init-char-array1.c
new file mode 100644
index 0000000..bd4ed68
--- /dev/null
+++ b/validation/init-char-array1.c
@@ -0,0 +1,28 @@
+/*
+ * for array of char, ("...") as the initializer is an gcc language
+ * extension. check that a parenthesized string initializer is handled
+ * correctly and that -Wparen-string warns about it's use.
+ */
+static const char u[] = ("hello");
+static const char v[] = {"hello"};
+static const char v1[] = {("hello")};
+static const char w[] = "hello";
+static const char x[5] = "hello";
+
+static void f(void)
+{
+	char a[1/(sizeof(u) == 6)];
+	char b[1/(sizeof(v) == 6)];
+	char b1[1/(sizeof(v1) == 6)];
+	char c[1/(sizeof(w) == 6)];
+	char d[1/(sizeof(x) == 5)];
+}
+/*
+ * check-name: parenthesized string initializer
+ * check-command: sparse -Wparen-string $file
+ *
+ * check-error-start
+init-char-array1.c:6:26: warning: array initialized from parenthesized string constant
+init-char-array1.c:8:28: warning: array initialized from parenthesized string constant
+ * check-error-end
+ */
-- 
1.8.2


--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux