[vala] Detect format string errors when instancing errors
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Detect format string errors when instancing errors
- Date: Mon, 7 Jul 2014 12:27:25 +0000 (UTC)
commit 7b6ee1be1e6b958a71911a6d5f5040e385a96a84
Author: Simon Werbeck <simon werbeck gmail com>
Date: Sun Jul 6 19:18:16 2014 +0200
Detect format string errors when instancing errors
Fixes bug 732530
vala/valamethodcall.vala | 115 +--------------------
vala/valaobjectcreationexpression.vala | 16 +++
vala/valasemanticanalyzer.vala | 178 +++++++++++++++++++++++++++-----
3 files changed, 168 insertions(+), 141 deletions(-)
---
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index 077131c..efce548 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -443,120 +443,7 @@ public class Vala.MethodCall : Expression {
}
if (format_literal != null) {
string format = format_literal.eval ();
-
- bool unsupported_format = false;
-
- weak string format_it = format;
- unichar c = format_it.get_char ();
- while (c != '\0') {
- if (c != '%') {
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- continue;
- }
-
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- // flags
- while (c == '#' || c == '0' || c == '-' || c == ' ' || c == '+') {
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- }
- // field width
- while (c >= '0' && c <= '9') {
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- }
- // precision
- if (c == '.') {
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- while (c >= '0' && c <= '9') {
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- }
- }
- // length modifier
- int length = 0;
- if (c == 'h') {
- length = -1;
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- if (c == 'h') {
- length = -2;
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- }
- } else if (c == 'l') {
- length = 1;
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- } else if (c == 'z') {
- length = 2;
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- }
- // conversion specifier
- DataType param_type = null;
- if (c == 'd' || c == 'i' || c == 'c') {
- // integer
- if (length == -2) {
- param_type = context.analyzer.int8_type;
- } else if (length == -1) {
- param_type = context.analyzer.short_type;
- } else if (length == 0) {
- param_type = context.analyzer.int_type;
- } else if (length == 1) {
- param_type = context.analyzer.long_type;
- } else if (length == 2) {
- param_type = context.analyzer.ssize_t_type;
- }
- } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
- // unsigned integer
- if (length == -2) {
- param_type = context.analyzer.uchar_type;
- } else if (length == -1) {
- param_type = context.analyzer.ushort_type;
- } else if (length == 0) {
- param_type = context.analyzer.uint_type;
- } else if (length == 1) {
- param_type = context.analyzer.ulong_type;
- } else if (length == 2) {
- param_type = context.analyzer.size_t_type;
- }
- } else if (c == 'e' || c == 'E' || c == 'f' || c == 'F'
- || c == 'g' || c == 'G' || c == 'a' || c == 'A') {
- // double
- param_type = context.analyzer.double_type;
- } else if (c == 's') {
- // string
- param_type = context.analyzer.string_type;
- } else if (c == 'p') {
- // pointer
- param_type = new PointerType (new VoidType ());
- } else if (c == '%') {
- // literal %
- } else {
- unsupported_format = true;
- break;
- }
- if (c != '\0') {
- format_it = format_it.next_char ();
- c = format_it.get_char ();
- }
- if (param_type != null) {
- if (arg_it.next ()) {
- Expression arg = arg_it.get ();
-
- arg.target_type = param_type;
- } else {
- Report.error (source_reference, "Too few arguments
for specified format");
- return false;
- }
- }
- }
- if (!unsupported_format && arg_it.next ()) {
- Report.error (source_reference, "Too many arguments for specified
format");
+ if (!context.analyzer.check_print_format (format, arg_it, source_reference)) {
return false;
}
}
diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala
index 939b8a6..e64b852 100644
--- a/vala/valaobjectcreationexpression.vala
+++ b/vala/valaobjectcreationexpression.vala
@@ -396,6 +396,22 @@ public class Vala.ObjectCreationExpression : Expression {
error = true;
Report.error (source_reference, "Invalid type for argument 1");
}
+
+ var format_literal = ex as StringLiteral;
+ if (format_literal != null) {
+ var format = format_literal.eval ();
+ if (!context.analyzer.check_print_format (format, arg_it,
source_reference)) {
+ error = true;
+ return false;
+ }
+ }
+
+ arg_it = get_argument_list ().iterator ();
+ arg_it.next ();
+ if (!context.analyzer.check_variadic_arguments (arg_it, 1, source_reference))
{
+ error = true;
+ return false;
+ }
}
}
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 97dad79..0cdd878 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -446,33 +446,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
}
- if (ellipsis) {
- while (arg_it != null && arg_it.next ()) {
- var arg = arg_it.get ();
- if (arg.error) {
- // ignore inner error
- expr.error = true;
- return false;
- } else if (arg.value_type is SignalType) {
- arg.error = true;
- Report.error (arg.source_reference, "Cannot pass signals as
arguments");
- return false;
- } else if (arg.value_type == null) {
- // disallow untyped arguments except for type inference of callbacks
- if (!(arg.symbol_reference is Method)) {
- expr.error = true;
- Report.error (expr.source_reference, "Invalid type for
argument %d".printf (i + 1));
- return false;
- }
- } else if (arg.target_type != null && !arg.value_type.compatible
(arg.target_type)) {
- // target_type known for printf arguments
- expr.error = true;
- Report.error (arg.source_reference, "Argument %d: Cannot convert from
`%s' to `%s'".printf (i + 1, arg.value_type.to_string (), arg.target_type.to_string ()));
- return false;
- }
-
- i++;
- }
+ if (ellipsis && !check_variadic_arguments (arg_it, i, expr.source_reference)) {
+ expr.error = true;
+ return false;
} else if (!ellipsis && arg_it != null && arg_it.next ()) {
expr.error = true;
var m = mtype as MethodType;
@@ -595,6 +571,154 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return true;
}
+ public bool check_variadic_arguments (Iterator<Expression> arg_it, int i, SourceReference
source_reference) {
+ while (arg_it != null && arg_it.next ()) {
+ var arg = arg_it.get ();
+ if (arg.error) {
+ // ignore inner error
+ return false;
+ } else if (arg.value_type is SignalType) {
+ arg.error = true;
+ Report.error (arg.source_reference, "Cannot pass signals as arguments");
+ return false;
+ } else if (arg.value_type == null) {
+ // disallow untyped arguments except for type inference of callbacks
+ if (!(arg.symbol_reference is Method)) {
+ Report.error (source_reference, "Invalid type for argument %d".printf
(i + 1));
+ return false;
+ }
+ } else if (arg.target_type != null && !arg.value_type.compatible (arg.target_type)) {
+ // target_type known for printf arguments
+ Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to
`%s'".printf (i + 1, arg.value_type.to_string (), arg.target_type.to_string ()));
+ return false;
+ }
+
+ i++;
+ }
+
+ return true;
+ }
+
+ public bool check_print_format (string format, Iterator<Expression> arg_it, SourceReference
source_reference) {
+ bool unsupported_format = false;
+
+ weak string format_it = format;
+ unichar c = format_it.get_char ();
+ while (c != '\0') {
+ if (c != '%') {
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ continue;
+ }
+
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ // flags
+ while (c == '#' || c == '0' || c == '-' || c == ' ' || c == '+') {
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ }
+ // field width
+ while (c >= '0' && c <= '9') {
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ }
+ // precision
+ if (c == '.') {
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ while (c >= '0' && c <= '9') {
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ }
+ }
+ // length modifier
+ int length = 0;
+ if (c == 'h') {
+ length = -1;
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ if (c == 'h') {
+ length = -2;
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ }
+ } else if (c == 'l') {
+ length = 1;
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ } else if (c == 'z') {
+ length = 2;
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ }
+ // conversion specifier
+ DataType param_type = null;
+ if (c == 'd' || c == 'i' || c == 'c') {
+ // integer
+ if (length == -2) {
+ param_type = context.analyzer.int8_type;
+ } else if (length == -1) {
+ param_type = context.analyzer.short_type;
+ } else if (length == 0) {
+ param_type = context.analyzer.int_type;
+ } else if (length == 1) {
+ param_type = context.analyzer.long_type;
+ } else if (length == 2) {
+ param_type = context.analyzer.ssize_t_type;
+ }
+ } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
+ // unsigned integer
+ if (length == -2) {
+ param_type = context.analyzer.uchar_type;
+ } else if (length == -1) {
+ param_type = context.analyzer.ushort_type;
+ } else if (length == 0) {
+ param_type = context.analyzer.uint_type;
+ } else if (length == 1) {
+ param_type = context.analyzer.ulong_type;
+ } else if (length == 2) {
+ param_type = context.analyzer.size_t_type;
+ }
+ } else if (c == 'e' || c == 'E' || c == 'f' || c == 'F'
+ || c == 'g' || c == 'G' || c == 'a' || c == 'A') {
+ // double
+ param_type = context.analyzer.double_type;
+ } else if (c == 's') {
+ // string
+ param_type = context.analyzer.string_type;
+ } else if (c == 'p') {
+ // pointer
+ param_type = new PointerType (new VoidType ());
+ } else if (c == '%') {
+ // literal %
+ } else {
+ unsupported_format = true;
+ break;
+ }
+ if (c != '\0') {
+ format_it = format_it.next_char ();
+ c = format_it.get_char ();
+ }
+ if (param_type != null) {
+ if (arg_it.next ()) {
+ Expression arg = arg_it.get ();
+
+ arg.target_type = param_type;
+ } else {
+ Report.error (source_reference, "Too few arguments for specified
format");
+ return false;
+ }
+ }
+ }
+ if (!unsupported_format && arg_it.next ()) {
+ Report.error (source_reference, "Too many arguments for specified format");
+ return false;
+ }
+
+ return true;
+ }
+
private static DataType? get_instance_base_type (DataType instance_type, DataType base_type, CodeNode
node_reference) {
// construct a new type reference for the base type with correctly linked type arguments
ReferenceType instance_base_type;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]