@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 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 (currently [`@tiden/playwright-reporter`](https://github.com/qase-tms/tiden-javascript/blob/main/playwright/README.md)).
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
- let expectedResult = null;
11
- let data = null;
12
- let cleanedString = input;
13
- const hasExpectedResult = input.includes('TidenExpRes:');
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
- return { expectedResult, data, cleanedString };
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiden/reporter-commons",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Tiden JS Reporters",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",