diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll index d189dd36f87..624465761c2 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll @@ -459,6 +459,13 @@ class FormatLiteral extends Literal instanceof StringLiteral { */ int getConvSpecOffset(int n) { result = this.getFormat().indexOf("%", n, 0) } + /** + * Gets the nth conversion specifier string. + */ + private string getConvSpecString(int n) { + n >= 0 and result = "%" + this.getFormat().splitAt("%", n + 1) + } + /* * Each of these predicates gets a regular expressions to match each individual * parts of a conversion specifier. @@ -524,22 +531,20 @@ class FormatLiteral extends Literal instanceof StringLiteral { int n, string spec, string params, string flags, string width, string prec, string len, string conv ) { - exists(int offset, string fmt, string rst, string regexp | - offset = this.getConvSpecOffset(n) and - fmt = this.getFormat() and - rst = fmt.substring(offset, fmt.length()) and + exists(string convSpec, string regexp | + convSpec = this.getConvSpecString(n) and regexp = this.getConvSpecRegexp() and ( - spec = rst.regexpCapture(regexp, 1) and - params = rst.regexpCapture(regexp, 2) and - flags = rst.regexpCapture(regexp, 3) and - width = rst.regexpCapture(regexp, 4) and - prec = rst.regexpCapture(regexp, 5) and - len = rst.regexpCapture(regexp, 6) and - conv = rst.regexpCapture(regexp, 7) + spec = convSpec.regexpCapture(regexp, 1) and + params = convSpec.regexpCapture(regexp, 2) and + flags = convSpec.regexpCapture(regexp, 3) and + width = convSpec.regexpCapture(regexp, 4) and + prec = convSpec.regexpCapture(regexp, 5) and + len = convSpec.regexpCapture(regexp, 6) and + conv = convSpec.regexpCapture(regexp, 7) or - spec = rst.regexpCapture(regexp, 1) and - not exists(rst.regexpCapture(regexp, 2)) and + spec = convSpec.regexpCapture(regexp, 1) and + not exists(convSpec.regexpCapture(regexp, 2)) and params = "" and flags = "" and width = "" and @@ -554,12 +559,10 @@ class FormatLiteral extends Literal instanceof StringLiteral { * Gets the nth conversion specifier (including the initial `%`). */ string getConvSpec(int n) { - exists(int offset, string fmt, string rst, string regexp | - offset = this.getConvSpecOffset(n) and - fmt = this.getFormat() and - rst = fmt.substring(offset, fmt.length()) and + exists(string convSpec, string regexp | + convSpec = this.getConvSpecString(n) and regexp = this.getConvSpecRegexp() and - result = rst.regexpCapture(regexp, 1) + result = convSpec.regexpCapture(regexp, 1) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll b/cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll index f032ba4749e..98280a522cf 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll @@ -194,6 +194,13 @@ class ScanfFormatLiteral extends Expr { ) } + /** + * Gets the nth conversion specifier string. + */ + private string getConvSpecString(int n) { + n >= 0 and result = "%" + this.getFormat().splitAt("%", n + 1) + } + /** * Gets the regular expression to match each individual part of a conversion specifier. */ @@ -227,16 +234,14 @@ class ScanfFormatLiteral extends Expr { * specifier. */ predicate parseConvSpec(int n, string spec, string width, string len, string conv) { - exists(int offset, string fmt, string rst, string regexp | - offset = this.getConvSpecOffset(n) and - fmt = this.getFormat() and - rst = fmt.substring(offset, fmt.length()) and + exists(string convSpec, string regexp | + convSpec = this.getConvSpecString(n) and regexp = this.getConvSpecRegexp() and ( - spec = rst.regexpCapture(regexp, 1) and - width = rst.regexpCapture(regexp, 2) and - len = rst.regexpCapture(regexp, 3) and - conv = rst.regexpCapture(regexp, 4) + spec = convSpec.regexpCapture(regexp, 1) and + width = convSpec.regexpCapture(regexp, 2) and + len = convSpec.regexpCapture(regexp, 3) and + conv = convSpec.regexpCapture(regexp, 4) ) ) }