@@ -21,7 +21,15 @@ class CqlClauseWithStringConcatParameter instanceof CqlClause {
2121 (
2222 if this instanceof CqlInsertClause or this instanceof CqlUpsertClause
2323 then
24- queryParameter = this .getArgument ( ) .flow ( ) or
24+ queryParameter = this .getArgument ( ) .flow ( )
25+ or
26+ /*
27+ * Account for cases where an object with a string concatenation is passed. e.g.
28+ * ``` javascript
29+ * let insertQuery = INSERT.into`SomeEntity`.entries({col1: "column_" + col});
30+ * ```
31+ */
32+
2533 queryParameter = this .getArgument ( ) .flow ( ) .( SourceNode ) .getAPropertyWrite ( ) .getRhs ( )
2634 else queryParameter = this .getArgument ( ) .flow ( )
2735 ) and
@@ -34,6 +42,10 @@ class CqlClauseWithStringConcatParameter instanceof CqlClause {
3442 string toString ( ) { result = super .toString ( ) }
3543}
3644
45+ /**
46+ * An await expression that has as its operand a CQL clause that includes a
47+ * string concatenation operation.
48+ */
3749class AwaitCqlClauseWithStringConcatParameter extends CqlInjectionSink {
3850 DataFlow:: Node queryParameter ;
3951 DataFlow:: Node query ;
@@ -49,17 +61,46 @@ class AwaitCqlClauseWithStringConcatParameter extends CqlInjectionSink {
4961 override DataFlow:: Node getQuery ( ) { result = cqlClauseWithStringConcat .( CqlClause ) .flow ( ) }
5062}
5163
52- class ParameterOfCqlRunMethodQueryArgument extends CqlInjectionSink {
64+ /**
65+ * The first argument passed to the call to `cds.run`, `cds.db.run`, or `srv.run`
66+ * whose value is a CQL query object that includes a string concatenation. e.g.
67+ * ``` javascript
68+ * // 1. CQN object constructed from Fluent API
69+ * const query = SELECT.from`Entity1`.where("ID=" + id);
70+ * cds.run(query);
71+ *
72+ * // 2. CQN object parsed from a string
73+ * const query = cds.parse.cql("SELECT * from Entity1 where ID =" + id);
74+ * cds.run(query);
75+ *
76+ * // 3. An unparsed CQL string (only valid in old versions of CAP)
77+ * const query = "SELECT * from Entity1 where ID =" + id;
78+ * Service2.run(query);
79+ * ```
80+ * The `getQuery/0` member predicate gets the `query` argument of the above calls
81+ * to `run`
82+ */
83+ class StringConcatParameterOfCqlRunMethodQueryArgument extends CqlInjectionSink {
5384 CqlRunMethodCall cqlRunMethodCall ;
5485
55- ParameterOfCqlRunMethodQueryArgument ( ) { this = cqlRunMethodCall .getAQueryParameter ( ) }
86+ StringConcatParameterOfCqlRunMethodQueryArgument ( ) {
87+ this = cqlRunMethodCall .getAQueryParameter ( )
88+ }
5689
5790 override DataFlow:: Node getQuery ( ) { result = this }
5891}
5992
6093/**
6194 * A CQL shortcut method call (`read`, `create`, ...) parameterized with a string
62- * concatenation expression.
95+ * concatenation expression. e.g.
96+ * ``` javascript
97+ * cds.read("Entity1").where(`ID=${id}`); // Notice the surrounding parentheses!
98+ * cds.create("Entity1").entries({id: "" + id});
99+ * cds.update("Entity1").set("col1 = col1" + amount).where("col1 = " + id);
100+ * cds.insert("Entity1").entries({id: "" + id});
101+ * cds.upsert("Entity1").entries({id: "" + id});
102+ * cds.delete("Entity1").where("ID =" + id);
103+ * ```
63104 */
64105class CqlShortcutMethodCallWithStringConcat instanceof CqlShortcutMethodCall {
65106 DataFlow:: Node stringConcatParameter ;
@@ -76,6 +117,23 @@ class CqlShortcutMethodCallWithStringConcat instanceof CqlShortcutMethodCall {
76117 DataFlow:: Node getStringConcatParameter ( ) { result = stringConcatParameter }
77118}
78119
120+ /**
121+ * A string concatenation expression included in a CQL shortcut method call. e.g.
122+ * ``` javascript
123+ * cds.read("Entity1").where(`ID=${id}`); // Notice the surrounding parentheses!
124+ * cds.create("Entity1").entries({id: "" + id});
125+ * cds.update("Entity1").set("col1 = col1" + amount).where("col1 = " + id);
126+ * cds.insert("Entity1").entries({id: "" + id});
127+ * cds.upsert("Entity1").entries({id: "" + id});
128+ * cds.delete("Entity1").where("ID =" + id);
129+ * ```
130+ * This class captures the string concatenation expressions appearing above:
131+ * 1. `ID=${id}`
132+ * 2. `"" + id`
133+ * 3. `"col1 = col1" + amount`
134+ * 4. `"col1 = " + id`
135+ * 5. `"ID =" + id`
136+ */
79137class StringConcatParameterOfCqlShortcutMethodCall extends CqlInjectionSink {
80138 CqlShortcutMethodCallWithStringConcat cqlShortcutMethodCallWithStringConcat ;
81139
0 commit comments