linux-sparse.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] teach sparse about wide string initializers
@ 2020-08-08 16:11 Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 1/6] wstring: add support for evaluation of wide string Luc Van Oostenryck
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Luc Van Oostenryck @ 2020-08-08 16:11 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

This series adds support for wide string initializers.
It's obviously not much important for the kernel but it's
used in a few places related to EFI.

Luc Van Oostenryck (6):
  wstring: add support for evaluation of wide string
  wstring: add support for checking size in string initializer
  wstring: add support for examination of string initialization
  wstring: add helper is_wchar_type()
  wstring: extend is_string_type() to also detect wide strings
  wstring: call is_string_type() only when needed

 evaluate.c                | 25 ++++++++++++++----------
 symbol.c                  | 25 ++++++++++++++++++++++++
 symbol.h                  |  7 +++++++
 validation/init-wstring.c | 40 +++++++++++++++++++++++++++++++++++++++
 validation/init_cstring.c |  2 ++
 5 files changed, 89 insertions(+), 10 deletions(-)
 create mode 100644 validation/init-wstring.c


base-commit: e1578773182e8f69c3a0cd8add8dfbe7561a8240
-- 
2.28.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/6] wstring: add support for evaluation of wide string
  2020-08-08 16:11 [PATCH 0/6] teach sparse about wide string initializers Luc Van Oostenryck
@ 2020-08-08 16:11 ` Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 2/6] wstring: add support for checking size in string initializer Luc Van Oostenryck
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luc Van Oostenryck @ 2020-08-08 16:11 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Evaluation doesn't know about wide strings.

Fix this by:
1) selecting the right base type (char_ctype vs wchar_ctype)
2) adapting the type, size & alignment of the underlying array
   to this base type.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 evaluate.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/evaluate.c b/evaluate.c
index dddea76182ad..acad11ab2712 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -102,9 +102,10 @@ static struct symbol *evaluate_string(struct expression *expr)
 	struct expression *addr = alloc_expression(expr->pos, EXPR_SYMBOL);
 	struct expression *initstr = alloc_expression(expr->pos, EXPR_STRING);
 	unsigned int length = expr->string->length;
+	struct symbol *char_type = expr->wide ? wchar_ctype : &char_ctype;
 
 	sym->array_size = alloc_const_expression(expr->pos, length);
-	sym->bit_size = bytes_to_bits(length);
+	sym->bit_size = length * char_type->bit_size;
 	sym->ctype.alignment = 1;
 	sym->string = 1;
 	sym->ctype.modifiers = MOD_STATIC;
@@ -117,10 +118,10 @@ static struct symbol *evaluate_string(struct expression *expr)
 	initstr->string = expr->string;
 
 	array->array_size = sym->array_size;
-	array->bit_size = bytes_to_bits(length);
-	array->ctype.alignment = 1;
+	array->bit_size = sym->bit_size;
+	array->ctype.alignment = char_type->ctype.alignment;
 	array->ctype.modifiers = MOD_STATIC;
-	array->ctype.base_type = &char_ctype;
+	array->ctype.base_type = char_type;
 	array->examined = 1;
 	array->evaluated = 1;
 	
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/6] wstring: add support for checking size in string initializer
  2020-08-08 16:11 [PATCH 0/6] teach sparse about wide string initializers Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 1/6] wstring: add support for evaluation of wide string Luc Van Oostenryck
@ 2020-08-08 16:11 ` Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 3/6] wstring: add support for examination of string initialization Luc Van Oostenryck
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luc Van Oostenryck @ 2020-08-08 16:11 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

A warning is given for string initializers if the LHS array
is not large enough to contains the string. But this check
doesn't knowns about wide strings.

Fix this by selecting the correct char type and use this type
for the size calculations.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 evaluate.c                |  6 ++++--
 validation/init-wstring.c | 41 +++++++++++++++++++++++++++++++++++++++
 validation/init_cstring.c |  2 ++
 3 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/evaluate.c b/evaluate.c
index acad11ab2712..bbfa77c3a79d 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -2841,10 +2841,12 @@ String:
 	*p = *e;
 	type = evaluate_expression(p);
 	if (ctype->bit_size != -1) {
-		if (ctype->bit_size + bits_in_char < type->bit_size)
+		struct symbol *char_type = e->wide ? wchar_ctype : &char_ctype;
+		unsigned int size_with_null = ctype->bit_size + char_type->bit_size;
+		if (size_with_null < type->bit_size)
 			warning(e->pos,
 				"too long initializer-string for array of char");
-		else if (Winit_cstring && ctype->bit_size + bits_in_char == type->bit_size) {
+		else if (Winit_cstring && size_with_null == type->bit_size) {
 			warning(e->pos,
 				"too long initializer-string for array of char(no space for nul char)");
 		}
diff --git a/validation/init-wstring.c b/validation/init-wstring.c
new file mode 100644
index 000000000000..846b6e2c3efd
--- /dev/null
+++ b/validation/init-wstring.c
@@ -0,0 +1,41 @@
+static const __WCHAR_TYPE__ ok0[] = L"abc";
+_Static_assert(sizeof(ok0) == 4 * sizeof(__WCHAR_TYPE__));
+static const __WCHAR_TYPE__ ok1[] = (L"abc");
+_Static_assert(sizeof(ok1) == 4 * sizeof(__WCHAR_TYPE__));
+static const __WCHAR_TYPE__ ok2[] = { L"abc" };
+_Static_assert(sizeof(ok2) == 4 * sizeof(__WCHAR_TYPE__));
+
+static const __WCHAR_TYPE__ ok3[4] = L"abc";
+_Static_assert(sizeof(ok3) == 4 * sizeof(__WCHAR_TYPE__));
+static const __WCHAR_TYPE__ ok4[4] = (L"abc");
+_Static_assert(sizeof(ok4) == 4 * sizeof(__WCHAR_TYPE__));
+static const __WCHAR_TYPE__ ok5[4] = { (L"abc") };
+_Static_assert(sizeof(ok5) == 4 * sizeof(__WCHAR_TYPE__));
+
+static const __WCHAR_TYPE__ ok6[7] = L"abc";
+_Static_assert(sizeof(ok6) == 7 * sizeof(__WCHAR_TYPE__));
+static const __WCHAR_TYPE__ ok7[7] = (L"abc");
+_Static_assert(sizeof(ok7) == 7 * sizeof(__WCHAR_TYPE__));
+static const __WCHAR_TYPE__ ok8[7] = { (L"abc") };
+_Static_assert(sizeof(ok8) == 7 * sizeof(__WCHAR_TYPE__));
+
+static const __WCHAR_TYPE__ *ptr[] =  { L"abc" };
+_Static_assert(sizeof(ptr) == sizeof(void *));
+
+static struct s {
+	const __WCHAR_TYPE__ str[4];
+} str = { L"xyz" };
+
+static const __WCHAR_TYPE__ ko3[3] = L"abc";
+static const __WCHAR_TYPE__ ko2[2] = L"abc";
+
+/*
+ * check-name: init-wstring
+ * check-command: sparse -Winit-cstring $file
+ * check-known-to-fail
+ *
+ * check-error-start
+init-wstring.c:29:38: warning: too long initializer-string for array of char(no space for nul char)
+init-wstring.c:30:38: warning: too long initializer-string for array of char
+ * check-error-end
+ */
diff --git a/validation/init_cstring.c b/validation/init_cstring.c
index 00eca20aa506..bac814e42907 100644
--- a/validation/init_cstring.c
+++ b/validation/init_cstring.c
@@ -1,11 +1,13 @@
 static struct alpha {
   char a[2];
 } x = { .a = "ab" };
+static const char str[2] = "abc";
 /*
  * check-name: -Winit-cstring option
  *
  * check-command: sparse -Winit-cstring $file
  * check-error-start
 init_cstring.c:3:14: warning: too long initializer-string for array of char(no space for nul char)
+init_cstring.c:4:28: warning: too long initializer-string for array of char
  * check-error-end
  */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/6] wstring: add support for examination of string initialization
  2020-08-08 16:11 [PATCH 0/6] teach sparse about wide string initializers Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 1/6] wstring: add support for evaluation of wide string Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 2/6] wstring: add support for checking size in string initializer Luc Van Oostenryck
@ 2020-08-08 16:11 ` Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 4/6] wstring: add helper is_wchar_type() Luc Van Oostenryck
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luc Van Oostenryck @ 2020-08-08 16:11 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

The examination of a string initializer doesn't know about wide
strings. The only thing needed is if the base type is some kind
of char but for wide chars, this type is the same as 'int' and
an array of ints can't be treated the same as an array of chars.

So, do the detection for wide string initializers as:
1) check that the LHS base type is wchar_ctype
2) check that the RHS is a kind of string expression
   (possibly between braces or parenthesis, recursively).

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 symbol.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/symbol.c b/symbol.c
index 6fcb1b150d27..7f0c85580f06 100644
--- a/symbol.c
+++ b/symbol.c
@@ -307,6 +307,29 @@ void merge_type(struct symbol *sym, struct symbol *base_type)
 		merge_type(sym, sym->ctype.base_type);
 }
 
+static bool is_wstring_expr(struct expression *expr)
+{
+	while (expr) {
+		switch (expr->type) {
+		case EXPR_STRING:
+			return 1;
+		case EXPR_INITIALIZER:
+			if (expression_list_size(expr->expr_list) != 1)
+				return 0;
+			expr = first_expression(expr->expr_list);
+			break;
+		case EXPR_PREOP:
+			if (expr->op == '(') {
+				expr = expr->unop;
+				break;
+			}
+		default:
+			return 0;
+		}
+	}
+	return 0;
+}
+
 static int count_array_initializer(struct symbol *t, struct expression *expr)
 {
 	int nr = 0;
@@ -321,6 +344,8 @@ static int count_array_initializer(struct symbol *t, struct expression *expr)
 	 */
 	if (t->ctype.base_type == &int_type && t->rank == -2)
 		is_char = 1;
+	else if (t == wchar_ctype && is_wstring_expr(expr))
+		is_char = 1;
 
 	switch (expr->type) {
 	case EXPR_INITIALIZER: {
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/6] wstring: add helper is_wchar_type()
  2020-08-08 16:11 [PATCH 0/6] teach sparse about wide string initializers Luc Van Oostenryck
                   ` (2 preceding siblings ...)
  2020-08-08 16:11 ` [PATCH 3/6] wstring: add support for examination of string initialization Luc Van Oostenryck
@ 2020-08-08 16:11 ` Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 5/6] wstring: extend is_string_type() to also detect wide strings Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 6/6] wstring: call is_string_type() only when needed Luc Van Oostenryck
  5 siblings, 0 replies; 7+ messages in thread
From: Luc Van Oostenryck @ 2020-08-08 16:11 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Like is_byte_type() but for wide chars.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 symbol.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/symbol.h b/symbol.h
index 8e7a286019c7..0e15f7bf6ba8 100644
--- a/symbol.h
+++ b/symbol.h
@@ -430,6 +430,13 @@ static inline int is_byte_type(struct symbol *type)
 	return type->bit_size == bits_in_char && type->type != SYM_BITFIELD;
 }
 
+static inline int is_wchar_type(struct symbol *type)
+{
+	if (type->type == SYM_NODE)
+		type = type->ctype.base_type;
+	return type == wchar_ctype;
+}
+
 static inline int is_void_type(struct symbol *type)
 {
 	if (type->type == SYM_NODE)
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/6] wstring: extend is_string_type() to also detect wide strings
  2020-08-08 16:11 [PATCH 0/6] teach sparse about wide string initializers Luc Van Oostenryck
                   ` (3 preceding siblings ...)
  2020-08-08 16:11 ` [PATCH 4/6] wstring: add helper is_wchar_type() Luc Van Oostenryck
@ 2020-08-08 16:11 ` Luc Van Oostenryck
  2020-08-08 16:11 ` [PATCH 6/6] wstring: call is_string_type() only when needed Luc Van Oostenryck
  5 siblings, 0 replies; 7+ messages in thread
From: Luc Van Oostenryck @ 2020-08-08 16:11 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

When evaluating initializers, it must be known if it is for a string
or not. But sparse doesn't known about wide strings.

Fix this by modifying is_string_type() to use is_wchar_type()
in addition of is_byte_type().

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 evaluate.c                | 5 ++++-
 validation/init-wstring.c | 1 -
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/evaluate.c b/evaluate.c
index bbfa77c3a79d..8d09c560e7fe 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -406,7 +406,10 @@ static inline int is_string_type(struct symbol *type)
 {
 	if (type->type == SYM_NODE)
 		type = type->ctype.base_type;
-	return type->type == SYM_ARRAY && is_byte_type(type->ctype.base_type);
+	if (type->type != SYM_ARRAY)
+		return 0;
+	type = type->ctype.base_type;
+	return is_byte_type(type) || is_wchar_type(type);
 }
 
 static struct symbol *bad_expr_type(struct expression *expr)
diff --git a/validation/init-wstring.c b/validation/init-wstring.c
index 846b6e2c3efd..d9ce3b3c883b 100644
--- a/validation/init-wstring.c
+++ b/validation/init-wstring.c
@@ -32,7 +32,6 @@ static const __WCHAR_TYPE__ ko2[2] = L"abc";
 /*
  * check-name: init-wstring
  * check-command: sparse -Winit-cstring $file
- * check-known-to-fail
  *
  * check-error-start
 init-wstring.c:29:38: warning: too long initializer-string for array of char(no space for nul char)
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/6] wstring: call is_string_type() only when needed
  2020-08-08 16:11 [PATCH 0/6] teach sparse about wide string initializers Luc Van Oostenryck
                   ` (4 preceding siblings ...)
  2020-08-08 16:11 ` [PATCH 5/6] wstring: extend is_string_type() to also detect wide strings Luc Van Oostenryck
@ 2020-08-08 16:11 ` Luc Van Oostenryck
  5 siblings, 0 replies; 7+ messages in thread
From: Luc Van Oostenryck @ 2020-08-08 16:11 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Just a tiny code reorganization to call is_string_type()
only where & when needed.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 evaluate.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/evaluate.c b/evaluate.c
index 8d09c560e7fe..d2cf1c0ae3f8 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -2764,7 +2764,6 @@ static struct expression *handle_scalar(struct expression *e, int nested)
 static int handle_initializer(struct expression **ep, int nested,
 		int class, struct symbol *ctype, unsigned long mods)
 {
-	int is_string = is_string_type(ctype);
 	struct expression *e = *ep, *p;
 	struct symbol *type;
 
@@ -2798,7 +2797,7 @@ static int handle_initializer(struct expression **ep, int nested,
 	 * pathologies, so we don't need anything fancy here.
 	 */
 	if (e->type == EXPR_INITIALIZER) {
-		if (is_string) {
+		if (is_string_type(ctype)) {
 			struct expression *v = NULL;
 			int count = 0;
 
@@ -2819,7 +2818,7 @@ static int handle_initializer(struct expression **ep, int nested,
 	/* string */
 	if (is_string_literal(&e)) {
 		/* either we are doing array of char, or we'll have to dig in */
-		if (is_string) {
+		if (is_string_type(ctype)) {
 			*ep = e;
 			goto String;
 		}
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-08-08 16:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-08 16:11 [PATCH 0/6] teach sparse about wide string initializers Luc Van Oostenryck
2020-08-08 16:11 ` [PATCH 1/6] wstring: add support for evaluation of wide string Luc Van Oostenryck
2020-08-08 16:11 ` [PATCH 2/6] wstring: add support for checking size in string initializer Luc Van Oostenryck
2020-08-08 16:11 ` [PATCH 3/6] wstring: add support for examination of string initialization Luc Van Oostenryck
2020-08-08 16:11 ` [PATCH 4/6] wstring: add helper is_wchar_type() Luc Van Oostenryck
2020-08-08 16:11 ` [PATCH 5/6] wstring: extend is_string_type() to also detect wide strings Luc Van Oostenryck
2020-08-08 16:11 ` [PATCH 6/6] wstring: call is_string_type() only when needed Luc Van Oostenryck

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).