@tiden/reporter-commons 0.1.0 → 0.1.1
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/CHANGELOG.md +10 -0
- package/README.md +1 -1
- package/dist/internal/step-parser.d.ts +5 -0
- package/dist/internal/step-parser.js +36 -17
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1
|
|
4
|
+
|
|
5
|
+
- **Fixed a polynomial ReDoS in `extractAndCleanStep`** (CodeQL `js/polynomial-redos`, high).
|
|
6
|
+
Its single regex spanned both the `TidenExpRes:` and `TidenData:` markers and needed an
|
|
7
|
+
ambiguous `\s*:?\s*` prefix: for a run of N spaces there are O(N) ways to split them across
|
|
8
|
+
the two `\s*`, so a step name containing a long run of spaces backtracked polynomially.
|
|
9
|
+
Replaced with index-based slicing, matching what upstream `qase-javascript-commons` moved to.
|
|
10
|
+
- Two bugs fixed along the way: a single marker with no counterpart was silently ignored (the
|
|
11
|
+
old regex required both), and `.` dropped multiline marker values.
|
|
12
|
+
|
|
3
13
|
## 0.1.0
|
|
4
14
|
|
|
5
15
|
Initial Tiden fork release of `@tiden/reporter-commons`.
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ See the [root README](https://github.com/qase-tms/tiden-javascript/blob/main/REA
|
|
|
9
9
|
## Who uses this
|
|
10
10
|
|
|
11
11
|
This package is **not meant to be installed or configured directly** in a test project — it's a
|
|
12
|
-
dependency of framework-specific reporters (
|
|
12
|
+
dependency of framework-specific reporters ([`@tiden/playwright-reporter`](https://github.com/qase-tms/tiden-javascript/blob/main/playwright/README.md), [`@tiden/vitest-reporter`](https://github.com/qase-tms/tiden-javascript/blob/main/vitest/README.md), and [`@tiden/jest-reporter`](https://github.com/qase-tms/tiden-javascript/blob/main/jest/README.md)).
|
|
13
13
|
Install and configure the reporter for your framework instead; it composes this package's config
|
|
14
14
|
loader, env resolver, and API transport internally.
|
|
15
15
|
|
|
@@ -7,5 +7,10 @@ export interface ExtractedStep {
|
|
|
7
7
|
* Parses a step string for inline `TidenExpRes:` (expected result) and `TidenData:`
|
|
8
8
|
* (data) markers. Returns the extracted parts and the input string with markers
|
|
9
9
|
* removed. If no markers are present, returns nulls and the original string.
|
|
10
|
+
*
|
|
11
|
+
* Index-based rather than regex-matched: a single pattern spanning both markers
|
|
12
|
+
* needs an ambiguous `\s*:?\s*` prefix, which backtracks polynomially on a step
|
|
13
|
+
* name containing a long run of spaces (CodeQL js/polynomial-redos). Slicing is
|
|
14
|
+
* linear, and it also keeps multiline marker values intact, which `.` did not.
|
|
10
15
|
*/
|
|
11
16
|
export declare function extractAndCleanStep(input: string): ExtractedStep;
|
|
@@ -1,28 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.extractAndCleanStep = extractAndCleanStep;
|
|
4
|
+
const EXPECTED_RESULT_MARKER = 'TidenExpRes:';
|
|
5
|
+
const DATA_MARKER = 'TidenData:';
|
|
6
|
+
/**
|
|
7
|
+
* Drops the marker's optional second colon and the surrounding whitespace, so
|
|
8
|
+
* that both `TidenExpRes: value` and `TidenExpRes:: value` yield `value`.
|
|
9
|
+
*
|
|
10
|
+
* Anchored and always matchable, so it cannot backtrack.
|
|
11
|
+
*/
|
|
12
|
+
function readMarkerValue(raw) {
|
|
13
|
+
return raw.replace(/^\s*:?\s*/, '').trim();
|
|
14
|
+
}
|
|
4
15
|
/**
|
|
5
16
|
* Parses a step string for inline `TidenExpRes:` (expected result) and `TidenData:`
|
|
6
17
|
* (data) markers. Returns the extracted parts and the input string with markers
|
|
7
18
|
* removed. If no markers are present, returns nulls and the original string.
|
|
19
|
+
*
|
|
20
|
+
* Index-based rather than regex-matched: a single pattern spanning both markers
|
|
21
|
+
* needs an ambiguous `\s*:?\s*` prefix, which backtracks polynomially on a step
|
|
22
|
+
* name containing a long run of spaces (CodeQL js/polynomial-redos). Slicing is
|
|
23
|
+
* linear, and it also keeps multiline marker values intact, which `.` did not.
|
|
8
24
|
*/
|
|
9
25
|
function extractAndCleanStep(input) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const hasData = input.includes('TidenData:');
|
|
15
|
-
if (hasExpectedResult || hasData) {
|
|
16
|
-
const regex = /TidenExpRes:\s*:?\s*(.*?)\s*(?=TidenData:|$)TidenData:\s*:?\s*(.*)?/;
|
|
17
|
-
const match = input.match(regex);
|
|
18
|
-
if (match) {
|
|
19
|
-
expectedResult = match[1]?.trim() ?? null;
|
|
20
|
-
data = match[2]?.trim() ?? null;
|
|
21
|
-
cleanedString = input
|
|
22
|
-
.replace(/TidenExpRes:\s*:?\s*.*?(?=TidenData:|$)/, '')
|
|
23
|
-
.replace(/TidenData:\s*:?\s*.*/, '')
|
|
24
|
-
.trim();
|
|
25
|
-
}
|
|
26
|
+
const expectedResultIndex = input.indexOf(EXPECTED_RESULT_MARKER);
|
|
27
|
+
const dataIndex = input.indexOf(DATA_MARKER);
|
|
28
|
+
if (expectedResultIndex === -1 && dataIndex === -1) {
|
|
29
|
+
return { expectedResult: null, data: null, cleanedString: input };
|
|
26
30
|
}
|
|
27
|
-
|
|
31
|
+
// Each marker's value runs until the next marker, or to the end of the input.
|
|
32
|
+
const expectedResultEnd = dataIndex > expectedResultIndex ? dataIndex : input.length;
|
|
33
|
+
const dataEnd = expectedResultIndex > dataIndex ? expectedResultIndex : input.length;
|
|
34
|
+
const expectedResult = expectedResultIndex === -1
|
|
35
|
+
? null
|
|
36
|
+
: readMarkerValue(input.slice(expectedResultIndex + EXPECTED_RESULT_MARKER.length, expectedResultEnd));
|
|
37
|
+
const data = dataIndex === -1
|
|
38
|
+
? ''
|
|
39
|
+
: readMarkerValue(input.slice(dataIndex + DATA_MARKER.length, dataEnd));
|
|
40
|
+
const markerIndexes = [expectedResultIndex, dataIndex].filter((index) => index !== -1);
|
|
41
|
+
return {
|
|
42
|
+
expectedResult,
|
|
43
|
+
// an omitted data value stays `null`, matching the long-standing contract
|
|
44
|
+
data: data === '' ? null : data,
|
|
45
|
+
cleanedString: input.slice(0, Math.min(...markerIndexes)).trim(),
|
|
46
|
+
};
|
|
28
47
|
}
|