diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll index bc63d740c321..cba3a94c7af3 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll @@ -3,3 +3,4 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis // Import each extension we want to enable import extensions.SubtractSelf import extensions.ConstantBitwiseAndExprRange +import extensions.StrlenLiteralRangeExpr diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/StrlenLiteralRangeExpr.qll b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/StrlenLiteralRangeExpr.qll new file mode 100644 index 000000000000..39326e89a518 --- /dev/null +++ b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/StrlenLiteralRangeExpr.qll @@ -0,0 +1,18 @@ +private import cpp +private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr + +/** + * Provides range analysis information for calls to `strlen` on literal strings. + * For example, the range of `strlen("literal")` will be 7. + */ +class StrlenLiteralRangeExpr extends SimpleRangeAnalysisExpr, FunctionCall { + StrlenLiteralRangeExpr() { + getTarget().hasGlobalOrStdName("strlen") and getArgument(0).isConstant() + } + + override int getLowerBounds() { result = getArgument(0).getValue().length() } + + override int getUpperBounds() { result = getArgument(0).getValue().length() } + + override predicate dependsOnChild(Expr e) { none() } +} diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.expected new file mode 100644 index 000000000000..f714ac312ea7 --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.expected @@ -0,0 +1,2 @@ +| test.cpp:4:3:4:8 | call to strlen | 7.0 | 7.0 | +| test.cpp:5:3:5:8 | call to strlen | 1.8446744073709552E19 | 0.0 | diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.ql b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.ql new file mode 100644 index 000000000000..c77b20786109 --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.ql @@ -0,0 +1,6 @@ +import cpp +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis +import experimental.semmle.code.cpp.rangeanalysis.extensions.StrlenLiteralRangeExpr + +from FunctionCall fc +select fc, upperBound(fc), lowerBound(fc) diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/test.cpp b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/test.cpp new file mode 100644 index 000000000000..02626c00f8f9 --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/test.cpp @@ -0,0 +1,6 @@ +unsigned long strlen(const char *); + +void func(const char *s) { + strlen("literal"); + strlen(s); +}