@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.
- package/build/abaplint.d.ts +5 -0
- package/build/src/abap/2_statements/expressions/field_chain.js +2 -2
- package/build/src/abap/2_statements/expressions/find_type.js +12 -0
- package/build/src/abap/2_statements/expressions/index.js +1 -0
- package/build/src/abap/2_statements/statements/find.js +1 -2
- package/build/src/abap/2_statements/statements/replace.js +1 -2
- package/build/src/abap/5_syntax/basic_types.js +14 -7
- package/build/src/abap/5_syntax/expressions/field_chain.js +5 -0
- package/build/src/registry.js +1 -1
- package/build/src/rules/allowed_object_naming.js +1 -1
- package/build/src/rules/dangerous_statement.js +25 -0
- package/build/src/rules/obsolete_statement.js +2 -3
- package/package.json +5 -5
package/build/abaplint.d.ts
CHANGED
|
@@ -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),
|
|
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")),
|
|
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"),
|
|
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(),
|
|
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
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
foundType =
|
|
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
|
-
|
|
483
|
-
|
|
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
|
}
|
package/build/src/registry.js
CHANGED
|
@@ -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_
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
60
|
+
"@types/node": "^16.11.6",
|
|
61
61
|
"chai": "^4.3.4",
|
|
62
|
-
"eslint": "^8.0
|
|
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.
|
|
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"
|