From 19c4b2ff8f2c47fcfda886ed5fcf427f43408123 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Mon, 13 Apr 2026 15:44:41 +0200 Subject: [PATCH] C++: Use `getConvSpecString` instead of `getConvSpecOffset` and `substring` --- cpp/ql/lib/semmle/code/cpp/commons/Printf.qll | 19 +++++++++++-------- cpp/ql/lib/semmle/code/cpp/commons/Scanf.qll | 13 +++++++++---- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll index d189dd36f87..253838d2ec3 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,10 +531,8 @@ 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 rst, string regexp | + rst = this.getConvSpecString(n) and regexp = this.getConvSpecRegexp() and ( spec = rst.regexpCapture(regexp, 1) and @@ -554,10 +559,8 @@ 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 rst, string regexp | + rst = this.getConvSpecString(n) and regexp = this.getConvSpecRegexp() and result = rst.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..b683530e822 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,10 +234,8 @@ 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 rst, string regexp | + rst = this.getConvSpecString(n) and regexp = this.getConvSpecRegexp() and ( spec = rst.regexpCapture(regexp, 1) and