@abaplint/core 2.79.31 → 2.79.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1655,6 +1655,7 @@ declare namespace Expressions {
1655
1655
  ClassGlobal_2 as ClassGlobal,
1656
1656
  ClassName,
1657
1657
  Color,
1658
+ FindType,
1658
1659
  CompareOperator,
1659
1660
  Compare,
1660
1661
  ComponentChainSimple,
@@ -1915,6 +1916,10 @@ declare class Find implements IStatement {
1915
1916
  getMatcher(): IStatementRunnable;
1916
1917
  }
1917
1918
 
1919
+ declare class FindType extends Expression {
1920
+ getRunnable(): IStatementRunnable;
1921
+ }
1922
+
1918
1923
  declare class FloatingPointType extends AbstractType {
1919
1924
  private readonly length;
1920
1925
  constructor(length: number, qualifiedName?: string);
@@ -6,9 +6,9 @@ const _1 = require(".");
6
6
  const tokens_1 = require("../../1_lexer/tokens");
7
7
  class FieldChain extends combi_1.Expression {
8
8
  getRunnable() {
9
- const attr = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.InstanceArrow), (0, combi_1.altPrio)(_1.AttributeName, "*"));
9
+ const attr = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.InstanceArrow), _1.AttributeName);
10
10
  const comp = (0, combi_1.seq)((0, combi_1.tok)(tokens_1.Dash), (0, combi_1.optPrio)(_1.ComponentName));
11
- const chain = (0, combi_1.star)((0, combi_1.altPrio)(attr, comp, _1.TableExpression));
11
+ const chain = (0, combi_1.star)((0, combi_1.altPrio)(_1.Dereference, attr, comp, _1.TableExpression));
12
12
  const clas = (0, combi_1.seq)(_1.ClassName, (0, combi_1.tok)(tokens_1.StaticArrow), _1.AttributeName);
13
13
  const start = (0, combi_1.altPrio)(clas, _1.SourceField, _1.SourceFieldSymbol);
14
14
  const after = (0, combi_1.altPrio)((0, combi_1.tok)(tokens_1.DashW), (0, combi_1.seq)((0, combi_1.optPrio)(_1.TableBody), (0, combi_1.optPrio)(_1.FieldOffset), (0, combi_1.optPrio)(_1.FieldLength)));
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FindType = void 0;
4
+ const version_1 = require("../../../version");
5
+ const combi_1 = require("../combi");
6
+ class FindType extends combi_1.Expression {
7
+ getRunnable() {
8
+ return (0, combi_1.opt)((0, combi_1.alt)("REGEX", "SUBSTRING", (0, combi_1.ver)(version_1.Version.v755, "PCRE")));
9
+ }
10
+ }
11
+ exports.FindType = FindType;
12
+ //# sourceMappingURL=find_type.js.map
@@ -27,6 +27,7 @@ __exportStar(require("./class_friends"), exports);
27
27
  __exportStar(require("./class_global"), exports);
28
28
  __exportStar(require("./class_name"), exports);
29
29
  __exportStar(require("./color"), exports);
30
+ __exportStar(require("./find_type"), exports);
30
31
  __exportStar(require("./compare_operator"), exports);
31
32
  __exportStar(require("./compare"), exports);
32
33
  __exportStar(require("./component_chain_simple"), exports);
@@ -3,14 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Find = void 0;
4
4
  const combi_1 = require("../combi");
5
5
  const expressions_1 = require("../expressions");
6
- const version_1 = require("../../../version");
7
6
  class Find {
8
7
  getMatcher() {
9
8
  // SUBMATCHES handling is a workaround
10
9
  const options = (0, combi_1.per)("IGNORING CASE", "RESPECTING CASE", "IN BYTE MODE", "IN CHARACTER MODE", (0, combi_1.seq)("OF", expressions_1.Source), (0, combi_1.seq)("FROM", expressions_1.Source), (0, combi_1.seq)("TO", expressions_1.Source), (0, combi_1.seq)("MATCH OFFSET", expressions_1.Target), (0, combi_1.seq)("MATCH LINE", expressions_1.Target), (0, combi_1.seq)("MATCH COUNT", expressions_1.Target), (0, combi_1.seq)("MATCH LENGTH", expressions_1.Target), (0, combi_1.seq)("LENGTH", expressions_1.Source), (0, combi_1.seq)("RESULTS", expressions_1.Target), (0, combi_1.seq)("SUBMATCHES", expressions_1.Target), (0, combi_1.seq)("SUBMATCHES", expressions_1.Target, expressions_1.Target), (0, combi_1.seq)("SUBMATCHES", (0, combi_1.plus)(expressions_1.Target)));
11
10
  const sectionLength = (0, combi_1.seq)("SECTION LENGTH", expressions_1.Source, "OF");
12
11
  const before = (0, combi_1.seq)((0, combi_1.optPrio)((0, combi_1.alt)("TABLE", "SECTION OFFSET", sectionLength)), expressions_1.Source);
13
- const ret = (0, combi_1.seq)("FIND", (0, combi_1.opt)((0, combi_1.alt)("FIRST OCCURRENCE OF", "ALL OCCURRENCES OF")), (0, combi_1.opt)((0, combi_1.alt)("REGEX", "SUBSTRING", (0, combi_1.ver)(version_1.Version.v755, "PCRE"))), expressions_1.Source, "IN", before, (0, combi_1.opt)(options));
12
+ const ret = (0, combi_1.seq)("FIND", (0, combi_1.opt)((0, combi_1.alt)("FIRST OCCURRENCE OF", "ALL OCCURRENCES OF")), expressions_1.FindType, expressions_1.Source, "IN", before, (0, combi_1.opt)(options));
14
13
  return ret;
15
14
  }
16
15
  }
@@ -3,13 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Replace = void 0;
4
4
  const combi_1 = require("../combi");
5
5
  const expressions_1 = require("../expressions");
6
- const version_1 = require("../../../version");
7
6
  class Replace {
8
7
  getMatcher() {
9
8
  const length = (0, combi_1.seq)("LENGTH", expressions_1.Source);
10
9
  const offset = (0, combi_1.seq)("OFFSET", expressions_1.Source);
11
10
  const section = (0, combi_1.seq)((0, combi_1.opt)("IN"), "SECTION", (0, combi_1.per)(offset, length), "OF", expressions_1.Source);
12
- const source = (0, combi_1.seq)((0, combi_1.opt)("OF"), (0, combi_1.opt)((0, combi_1.alt)("REGEX", "SUBSTRING", (0, combi_1.ver)(version_1.Version.v755, "PCRE"))), expressions_1.Source);
11
+ const source = (0, combi_1.seq)((0, combi_1.opt)("OF"), expressions_1.FindType, expressions_1.Source);
13
12
  const cas = (0, combi_1.alt)("IGNORING CASE", "RESPECTING CASE");
14
13
  const repl = (0, combi_1.seq)("REPLACEMENT COUNT", expressions_1.Target);
15
14
  const replo = (0, combi_1.seq)("REPLACEMENT OFFSET", expressions_1.Target);
@@ -164,7 +164,7 @@ class BasicTypes {
164
164
  }
165
165
  const type = this.scope.findTypePoolType(chainText);
166
166
  if (type) {
167
- this.scope.addReference(typeName.getFirstToken(), typ, _reference_1.ReferenceType.TypeReference, this.filename);
167
+ // this.scope.addReference(typeName.getFirstToken(), type, ReferenceType.TypeReference, this.filename);
168
168
  return type;
169
169
  }
170
170
  const ddic = this.scope.getDDIC().lookup(chainText);
@@ -474,13 +474,20 @@ class BasicTypes {
474
474
  const found = this.scope.findType(subs[0]);
475
475
  foundType = found === null || found === void 0 ? void 0 : found.getType();
476
476
  if (foundType === undefined) {
477
- const f = this.scope.getDDIC().lookupTableOrView(subs[0]);
478
- this.scope.getDDICReferences().addUsing(this.scope.getParentObj(), { object: f.object, filename: this.filename, token: expr.getFirstToken() });
479
- if (f.type instanceof _typed_identifier_1.TypedIdentifier) {
480
- foundType = f.type.getType();
477
+ const typePoolType = this.scope.findTypePoolType(subs[0]);
478
+ if (typePoolType) {
479
+ // this.scope.addReference(typeName.getFirstToken(), typePoolType, ReferenceType.TypeReference, this.filename);
480
+ foundType = typePoolType;
481
481
  }
482
- else {
483
- foundType = f.type;
482
+ if (foundType === undefined) {
483
+ const f = this.scope.getDDIC().lookupTableOrView(subs[0]);
484
+ this.scope.getDDICReferences().addUsing(this.scope.getParentObj(), { object: f.object, filename: this.filename, token: expr.getFirstToken() });
485
+ if (f.type instanceof _typed_identifier_1.TypedIdentifier) {
486
+ foundType = f.type.getType();
487
+ }
488
+ else {
489
+ foundType = f.type;
490
+ }
484
491
  }
485
492
  }
486
493
  else {
@@ -11,6 +11,8 @@ const _reference_1 = require("../_reference");
11
11
  const field_offset_1 = require("./field_offset");
12
12
  const field_length_1 = require("./field_length");
13
13
  const table_expression_1 = require("./table_expression");
14
+ const expressions_1 = require("../../2_statements/expressions");
15
+ const dereference_1 = require("./dereference");
14
16
  class FieldChain {
15
17
  runSyntax(node, scope, filename, refType) {
16
18
  const concat = node.concatTokens();
@@ -64,6 +66,9 @@ class FieldChain {
64
66
  throw new Error("Not a object reference, field chain");
65
67
  }
66
68
  }
69
+ else if (current.get() instanceof expressions_1.Dereference) {
70
+ context = new dereference_1.Dereference().runSyntax(context);
71
+ }
67
72
  else if (current.get() instanceof Expressions.ComponentName) {
68
73
  context = new component_name_1.ComponentName().runSyntax(context, current);
69
74
  }
@@ -68,7 +68,7 @@ class Registry {
68
68
  }
69
69
  static abaplintVersion() {
70
70
  // magic, see build script "version.sh"
71
- return "2.79.31";
71
+ return "2.79.35";
72
72
  }
73
73
  getDDICReferences() {
74
74
  return this.references;
@@ -42,7 +42,7 @@ class AllowedObjectNaming {
42
42
  message = "Name not allowed";
43
43
  }
44
44
  }
45
- else if (obj.getName().match(/^(\/[A-Z_\d]{3,8}\/)?[A-Z_\d<> ]+$/i) === null) {
45
+ else if (obj.getName().match(/^(\/[A-Z_\d]{3,8}\/)?[A-Z_-\d<> ]+$/i) === null) {
46
46
  message = "Name not allowed";
47
47
  }
48
48
  if (message.length > 0) {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DangerousStatement = exports.DangerousStatementConf = void 0;
4
4
  const Statements = require("../abap/2_statements/statements");
5
+ const Expressions = require("../abap/2_statements/expressions");
5
6
  const issue_1 = require("../issue");
6
7
  const _abap_rule_1 = require("./_abap_rule");
7
8
  const _basic_rule_config_1 = require("./_basic_rule_config");
@@ -24,6 +25,8 @@ class DangerousStatementConf extends _basic_rule_config_1.BasicRuleConfig {
24
25
  this.deleteTextpool = true;
25
26
  this.deleteDynpro = true;
26
27
  this.importDynpro = true;
28
+ /** Finds instances of dynamic SQL: SELECT, UPDATE, DELETE, INSERT, MODIFY */
29
+ this.dynamicSQL = true;
27
30
  }
28
31
  }
29
32
  exports.DangerousStatementConf = DangerousStatementConf;
@@ -37,6 +40,8 @@ class DangerousStatement extends _abap_rule_1.ABAPRule {
37
40
  key: "dangerous_statement",
38
41
  title: "Dangerous statement",
39
42
  shortDescription: `Detects potentially dangerous statements`,
43
+ extendedInformation: `Dynamic SQL: Typically ABAP logic does not need dynamic SQL,
44
+ dynamic SQL can potentially create SQL injection problems`,
40
45
  tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Security],
41
46
  };
42
47
  }
@@ -90,9 +95,29 @@ class DangerousStatement extends _abap_rule_1.ABAPRule {
90
95
  if (message) {
91
96
  issues.push(issue_1.Issue.atStatement(file, statementNode, this.getDescription(message), this.getMetadata().key, this.conf.severity));
92
97
  }
98
+ if (this.conf.dynamicSQL) {
99
+ message = this.findDynamicSQL(statementNode);
100
+ if (message) {
101
+ issues.push(issue_1.Issue.atStatement(file, statementNode, this.getDescription(message), this.getMetadata().key, this.conf.severity));
102
+ }
103
+ }
93
104
  }
94
105
  return issues;
95
106
  }
107
+ findDynamicSQL(statementNode) {
108
+ const statement = statementNode.get();
109
+ if (statement instanceof Statements.UpdateDatabase
110
+ || statement instanceof Statements.Select
111
+ || statement instanceof Statements.SelectLoop
112
+ || statement instanceof Statements.InsertDatabase
113
+ || statement instanceof Statements.ModifyDatabase
114
+ || statement instanceof Statements.DeleteDatabase) {
115
+ if (statementNode.findFirstExpression(Expressions.Dynamic)) {
116
+ return "Dynamic SQL";
117
+ }
118
+ }
119
+ return undefined;
120
+ }
96
121
  }
97
122
  exports.DangerousStatement = DangerousStatement;
98
123
  //# sourceMappingURL=dangerous_statement.js.map
@@ -123,7 +123,7 @@ POSIX REGEX: https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.ht
123
123
  this.conf = conf;
124
124
  }
125
125
  runParsed(file) {
126
- var _a, _b;
126
+ var _a, _b, _c;
127
127
  const issues = [];
128
128
  const statements = file.getStatements();
129
129
  let prev = undefined;
@@ -272,8 +272,7 @@ POSIX REGEX: https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.ht
272
272
  }
273
273
  if (configVersion >= version_1.Version.v756 && this.conf.regex) {
274
274
  if (sta instanceof Statements.Find || sta instanceof Statements.Replace) {
275
- const concat = staNode.concatTokens().toUpperCase();
276
- if (concat.includes("REGEX")) {
275
+ if ((_c = staNode.findFirstExpression(Expressions.FindType)) === null || _c === void 0 ? void 0 : _c.concatTokens().includes("REGEX")) {
277
276
  const issue = issue_1.Issue.atStatement(file, staNode, "REGEX obsolete, use PCRE", this.getMetadata().key, this.conf.severity);
278
277
  issues.push(issue);
279
278
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.79.31",
3
+ "version": "2.79.35",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -54,12 +54,12 @@
54
54
  },
55
55
  "homepage": "https://abaplint.org",
56
56
  "devDependencies": {
57
- "@microsoft/api-extractor": "^7.18.16",
57
+ "@microsoft/api-extractor": "^7.18.17",
58
58
  "@types/chai": "^4.2.22",
59
59
  "@types/mocha": "^9.0.0",
60
- "@types/node": "^16.11.1",
60
+ "@types/node": "^16.11.6",
61
61
  "chai": "^4.3.4",
62
- "eslint": "^8.0.1",
62
+ "eslint": "^8.1.0",
63
63
  "madge": "^5.0.1",
64
64
  "mocha": "^9.1.3",
65
65
  "c8": "^7.10.0",
@@ -68,7 +68,7 @@
68
68
  "typescript": "^4.4.4"
69
69
  },
70
70
  "dependencies": {
71
- "fast-xml-parser": "^3.20.3",
71
+ "fast-xml-parser": "^3.21.0",
72
72
  "json5": "^2.2.0",
73
73
  "vscode-languageserver-protocol": "^3.16.0",
74
74
  "vscode-languageserver-types": "^3.16.0"