按规划继续工作
结论:补齐 OPFS G-code 程序文件名的自定义路径与非法遍历/嵌套路径拒绝验证,覆盖 Node OPFS 与 Chromium OPFS 路径,并通过 host/WASM/browser 聚合验证。
This commit is contained in:
@@ -101,7 +101,8 @@ tool table, parameter, G-code, preview-cache, and session-snapshot storage
|
|||||||
targets. It also validates the host-side session snapshot JSON envelope and
|
targets. It also validates the host-side session snapshot JSON envelope and
|
||||||
round-trip store, including unsupported format/version, session-id mismatch,
|
round-trip store, including unsupported format/version, session-id mismatch,
|
||||||
non-object metadata/payload rejection, custom snapshot filenames, and invalid
|
non-object metadata/payload rejection, custom snapshot filenames, and invalid
|
||||||
snapshot filename rejection, plus pure-text machine file and G-code stores
|
snapshot filename rejection, plus pure-text machine file and G-code stores,
|
||||||
|
including G-code program filename rejection for traversal or nested paths,
|
||||||
without defining CNC machine-state or file-format semantics. It now also validates the
|
without defining CNC machine-state or file-format semantics. It now also validates the
|
||||||
OPFS-to-WASM parameter-file bridge with a mock interpreter SDK to ensure the
|
OPFS-to-WASM parameter-file bridge with a mock interpreter SDK to ensure the
|
||||||
host boundary copies text into and out of the WASM filesystem without defining
|
host boundary copies text into and out of the WASM filesystem without defining
|
||||||
@@ -115,7 +116,8 @@ The browser INI/OPFS smoke script serves `wasm-port/` over localhost and runs
|
|||||||
Chromium headless against a test page that imports the JS SDK, loads the INI
|
Chromium headless against a test page that imports the JS SDK, loads the INI
|
||||||
WASM module, queries vendored LinuxCNC INI parsing through the SDK, and
|
WASM module, queries vendored LinuxCNC INI parsing through the SDK, and
|
||||||
performs an OPFS text-file, generic session snapshot, custom snapshot filename,
|
performs an OPFS text-file, generic session snapshot, custom snapshot filename,
|
||||||
invalid snapshot filename/envelope, machine file, and G-code text round trip.
|
invalid snapshot filename/envelope, machine file, G-code text round trip, and
|
||||||
|
G-code filename path-model rejection.
|
||||||
|
|
||||||
The browser interpreter smoke script serves `wasm-port/` over localhost and
|
The browser interpreter smoke script serves `wasm-port/` over localhost and
|
||||||
runs Chromium headless against a test page that loads the interpreter-core
|
runs Chromium headless against a test page that loads the interpreter-core
|
||||||
@@ -186,8 +188,8 @@ The validation fails if:
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `tests/wasm/node/verify_ini_wasm.sh` | Validates the browser-facing INI WASM module can be built from vendored LinuxCNC `inifile.cc`, loaded through the JS SDK in Node, and queried through the exported C ABI. |
|
| `tests/wasm/node/verify_ini_wasm.sh` | Validates the browser-facing INI WASM module can be built from vendored LinuxCNC `inifile.cc`, loaded through the JS SDK in Node, and queried through the exported C ABI. |
|
||||||
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the initial interpreter-core WASM module can be built from vendored LinuxCNC interpreter source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
|
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the initial interpreter-core WASM module can be built from vendored LinuxCNC interpreter source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
|
||||||
| `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including custom filenames and envelope/path rejection paths, machine file store, G-code text store, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. |
|
| `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including custom filenames and envelope/path rejection paths, machine file store, G-code text store including filename rejection paths, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. |
|
||||||
| `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, OPFS text-file round trip, generic session snapshot round trip plus custom filename and envelope/path rejection paths, machine file text round trip, G-code text round trip, and the INI panel UI's machine-session load, G-code run, and canonical-event display paths in a real browser runtime. |
|
| `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, OPFS text-file round trip, generic session snapshot round trip plus custom filename and envelope/path rejection paths, machine file text round trip, G-code text round trip plus filename rejection paths, and the INI panel UI's machine-session load, G-code run, and canonical-event display paths in a real browser runtime. |
|
||||||
| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures through vendored LinuxCNC `Interp::execute()` plus `Interp::open()`/`read()`/`execute()` via the exported C ABI, including OPFS-backed parameter-file restore/save and tool-table load/save through vendored LinuxCNC source. |
|
| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures through vendored LinuxCNC `Interp::execute()` plus `Interp::open()`/`read()`/`execute()` via the exported C ABI, including OPFS-backed parameter-file restore/save and tool-table load/save through vendored LinuxCNC source. |
|
||||||
| `tests/host/verify_host_smokes.sh` | Runs the current host-side Node, WASM interpreter-core, OPFS, and browser smoke validation with shared WASM builds. |
|
| `tests/host/verify_host_smokes.sh` | Runs the current host-side Node, WASM interpreter-core, OPFS, and browser smoke validation with shared WASM builds. |
|
||||||
|
|
||||||
|
|||||||
@@ -71,8 +71,9 @@ semantic rewrites:
|
|||||||
file and G-code storage, parameter/tool-table bridge copying into the
|
file and G-code storage, parameter/tool-table bridge copying into the
|
||||||
interpreter SDK filesystem, grouped machine-session loading, explicit
|
interpreter SDK filesystem, grouped machine-session loading, explicit
|
||||||
session file-name overrides, invalid INI-derived machine file names, generic
|
session file-name overrides, invalid INI-derived machine file names, generic
|
||||||
session snapshot custom filenames plus envelope/path rejection paths, and a
|
session snapshot custom filenames plus envelope/path rejection paths, G-code
|
||||||
Chromium localhost round trip for those persistence paths.
|
program filename rejection paths, and a Chromium localhost round trip for
|
||||||
|
those persistence paths.
|
||||||
- Host-side smoke validation is aggregated by
|
- Host-side smoke validation is aggregated by
|
||||||
`tests/host/verify_host_smokes.sh` so Node, WASM, OPFS, and browser checks
|
`tests/host/verify_host_smokes.sh` so Node, WASM, OPFS, and browser checks
|
||||||
run from one command.
|
run from one command.
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ Current validation is intentionally mechanical:
|
|||||||
filenames under the session directory, and validates its format, version,
|
filenames under the session directory, and validates its format, version,
|
||||||
session id, metadata, payload shape, and filename boundary.
|
session id, metadata, payload shape, and filename boundary.
|
||||||
`runtime/opfs/machine-file-store.js` adds pure-text storage for INI, tool
|
`runtime/opfs/machine-file-store.js` adds pure-text storage for INI, tool
|
||||||
table, parameter file, and G-code program content.
|
table, parameter file, and G-code program content, with G-code program
|
||||||
|
filenames constrained by `runtime/opfs/path-model.js`.
|
||||||
`runtime/opfs/linuxcnc-parameter-bridge.js` copies OPFS-backed parameter
|
`runtime/opfs/linuxcnc-parameter-bridge.js` copies OPFS-backed parameter
|
||||||
files into the interpreter SDK filesystem and writes back the LinuxCNC-saved
|
files into the interpreter SDK filesystem and writes back the LinuxCNC-saved
|
||||||
parameter file plus backup. `runtime/opfs/linuxcnc-tool-table-bridge.js`
|
parameter file plus backup. `runtime/opfs/linuxcnc-tool-table-bridge.js`
|
||||||
|
|||||||
@@ -9,7 +9,11 @@
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
import { createLinuxCncIniSdk } from "../../runtime/sdk/src/index.js";
|
import { createLinuxCncIniSdk } from "../../runtime/sdk/src/index.js";
|
||||||
import { loadTextFile, saveTextFile } from "../../runtime/opfs/file-service.js";
|
import { loadTextFile, saveTextFile } from "../../runtime/opfs/file-service.js";
|
||||||
import { machineIniPath, sessionSnapshotPath } from "../../runtime/opfs/path-model.js";
|
import {
|
||||||
|
gcodeProgramPath,
|
||||||
|
machineIniPath,
|
||||||
|
sessionSnapshotPath,
|
||||||
|
} from "../../runtime/opfs/path-model.js";
|
||||||
import {
|
import {
|
||||||
loadSessionSnapshot,
|
loadSessionSnapshot,
|
||||||
saveSessionSnapshot,
|
saveSessionSnapshot,
|
||||||
@@ -201,8 +205,25 @@ JOINTS = 3
|
|||||||
assertEqual(machineFiles.ini, iniText, "machine ini text");
|
assertEqual(machineFiles.ini, iniText, "machine ini text");
|
||||||
assertEqual(machineFiles.toolTable, "T0 P0 ; no tool\n", "tool table text");
|
assertEqual(machineFiles.toolTable, "T0 P0 ; no tool\n", "tool table text");
|
||||||
assertEqual(machineFiles.parameters, "5161 0.0\n", "parameter text");
|
assertEqual(machineFiles.parameters, "5161 0.0\n", "parameter text");
|
||||||
|
assertEqual(
|
||||||
|
gcodeProgramPath("browser-custom.ngc"),
|
||||||
|
"linuxcnc/gcode/browser-custom.ngc",
|
||||||
|
"custom G-code path",
|
||||||
|
);
|
||||||
await saveGcodeProgram("browser-smoke.ngc", "G0 X0 Y0\nM2\n");
|
await saveGcodeProgram("browser-smoke.ngc", "G0 X0 Y0\nM2\n");
|
||||||
assertEqual(await loadGcodeProgram("browser-smoke.ngc"), "G0 X0 Y0\nM2\n", "gcode text");
|
assertEqual(await loadGcodeProgram("browser-smoke.ngc"), "G0 X0 Y0\nM2\n", "gcode text");
|
||||||
|
await saveGcodeProgram("browser-custom.ngc", "G1 X1 F10\nM2\n");
|
||||||
|
assertEqual(await loadGcodeProgram("browser-custom.ngc"), "G1 X1 F10\nM2\n", "custom gcode text");
|
||||||
|
await assertRejects(
|
||||||
|
"browser G-code invalid filename save",
|
||||||
|
() => saveGcodeProgram("nested/browser.ngc", ""),
|
||||||
|
/Invalid G-code filename/,
|
||||||
|
);
|
||||||
|
await assertRejects(
|
||||||
|
"browser G-code invalid filename load",
|
||||||
|
() => loadGcodeProgram("../escape.ngc"),
|
||||||
|
/Invalid G-code filename/,
|
||||||
|
);
|
||||||
|
|
||||||
const uiDocument = await loadUiFrame();
|
const uiDocument = await loadUiFrame();
|
||||||
await waitFor(
|
await waitFor(
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ assert.equal(machineIniPath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/machine.i
|
|||||||
assert.equal(toolTablePath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/tool.tbl");
|
assert.equal(toolTablePath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/tool.tbl");
|
||||||
assert.equal(parameterFilePath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/linuxcnc.var");
|
assert.equal(parameterFilePath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/linuxcnc.var");
|
||||||
assert.equal(gcodeProgramPath("fixture.ngc"), "linuxcnc/gcode/fixture.ngc");
|
assert.equal(gcodeProgramPath("fixture.ngc"), "linuxcnc/gcode/fixture.ngc");
|
||||||
|
assert.equal(gcodeProgramPath("custom-fixture.ngc"), "linuxcnc/gcode/custom-fixture.ngc");
|
||||||
assert.equal(previewCachePath("fixture"), "linuxcnc/preview-cache/fixture/preview.json");
|
assert.equal(previewCachePath("fixture"), "linuxcnc/preview-cache/fixture/preview.json");
|
||||||
assert.equal(sessionSnapshotPath("session-1"), "linuxcnc/sessions/session-1/snapshot.json");
|
assert.equal(sessionSnapshotPath("session-1"), "linuxcnc/sessions/session-1/snapshot.json");
|
||||||
assert.equal(
|
assert.equal(
|
||||||
@@ -204,6 +205,11 @@ assert.equal(
|
|||||||
"linuxcnc/gcode/fixture.ngc",
|
"linuxcnc/gcode/fixture.ngc",
|
||||||
);
|
);
|
||||||
assert.equal(await loadGcodeProgram("fixture.ngc", { storage }), "G0 X0 Y0\nM2\n");
|
assert.equal(await loadGcodeProgram("fixture.ngc", { storage }), "G0 X0 Y0\nM2\n");
|
||||||
|
assert.equal(
|
||||||
|
await saveGcodeProgram("custom-fixture.ngc", "G1 X1 F10\nM2\n", { storage }),
|
||||||
|
"linuxcnc/gcode/custom-fixture.ngc",
|
||||||
|
);
|
||||||
|
assert.equal(await loadGcodeProgram("custom-fixture.ngc", { storage }), "G1 X1 F10\nM2\n");
|
||||||
|
|
||||||
const bridgeFiles = new Map();
|
const bridgeFiles = new Map();
|
||||||
const bridgeInterp = {
|
const bridgeInterp = {
|
||||||
@@ -594,6 +600,18 @@ assert.throws(
|
|||||||
() => sessionSnapshotPath("session-1", "nested/snapshot.json"),
|
() => sessionSnapshotPath("session-1", "nested/snapshot.json"),
|
||||||
/Invalid session snapshot filename/,
|
/Invalid session snapshot filename/,
|
||||||
);
|
);
|
||||||
|
assert.throws(
|
||||||
|
() => gcodeProgramPath("../escape.ngc"),
|
||||||
|
/Invalid G-code filename/,
|
||||||
|
);
|
||||||
|
await assert.rejects(
|
||||||
|
() => saveGcodeProgram("nested/fixture.ngc", "", { storage }),
|
||||||
|
/Invalid G-code filename/,
|
||||||
|
);
|
||||||
|
await assert.rejects(
|
||||||
|
() => loadGcodeProgram("../escape.ngc", { storage }),
|
||||||
|
/Invalid G-code filename/,
|
||||||
|
);
|
||||||
await assert.rejects(
|
await assert.rejects(
|
||||||
() => saveSessionSnapshot("session-1", {}, {
|
() => saveSessionSnapshot("session-1", {}, {
|
||||||
storage,
|
storage,
|
||||||
|
|||||||
Reference in New Issue
Block a user