Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
a1ae774
chore(lua): add prep packet
prankster009 Jul 1, 2026
879e8d6
chore(lua): add frontend scaffold
prankster009 Jul 1, 2026
bab0adc
chore(lua): wire frontend into build graph
prankster009 Jul 1, 2026
1016e33
feat(lua2cpg): add runnable Lua entry smoke
prankster009 Jul 8, 2026
c495093
Add Lua bytecode decoder model
prankster009 Jul 8, 2026
6a356a9
Decode Lua byte strings deterministically
prankster009 Jul 8, 2026
e1b753d
Add Lua bytecode decoder unit tests
prankster009 Jul 8, 2026
9812be5
Emit Lua bytecode model into CPG
prankster009 Jul 8, 2026
c281df4
Gate Lua bytecode success fact emission
prankster009 Jul 8, 2026
eb6597a
style(lua2cpg): format Lua bytecode model
prankster009 Jul 8, 2026
a3e5d41
docs(lua2cpg): add bytecode model smoke
prankster009 Jul 8, 2026
3df1139
feat(lua2cpg): add Lua intraprocedural semantics smoke
prankster009 Jul 8, 2026
9748e4d
feat(lua2cpg): add interprocedural module taint semantics
prankster009 Jul 8, 2026
754c226
docs(lua2cpg): document interprocedural module taint smoke
prankster009 Jul 8, 2026
0d8ff32
refactor(lua2cpg): require explicit E4 resolution states
prankster009 Jul 8, 2026
9220a1e
feat(lua2cpg): add rules sanitizer report markers
prankster009 Jul 8, 2026
3727476
docs(lua2cpg): document rules sanitizer report smoke
prankster009 Jul 8, 2026
abfe1b3
docs(lua2cpg): add benchmark adapter runbook
prankster009 Jul 9, 2026
c1c2537
feat(lua2cpg): export real-firmware benchmark evidence
prankster009 Jul 9, 2026
aec716c
fix(lua2cpg): emit OpenWrt-derived real-firmware path reports
prankster009 Jul 9, 2026
0cce403
fix(lua2cpg): cover OpenWrt-derived real-firmware report families
prankster009 Jul 9, 2026
afdd31c
test(lua2cpg): add cross-platform path report red coverage
prankster009 Jul 9, 2026
a3cbb6b
fix(lua2cpg): cover cross-platform real-firmware path families
prankster009 Jul 9, 2026
d516065
fix(lua2cpg): prune cross-platform real-firmware path search
prankster009 Jul 10, 2026
d6e1472
fix(lua2cpg): require cross-platform source bridge for paths
prankster009 Jul 10, 2026
8df8fbf
fix(lua2cpg): classify cross-platform real-firmware sanitizers
prankster009 Jul 10, 2026
1bffaa3
test(lua2cpg): cover cross-platform r5 residual path sink rows
prankster009 Jul 10, 2026
594c77e
fix(lua2cpg): close cross-platform r5 residual path sink evidence
prankster009 Jul 11, 2026
acac56d
test(lua2cpg): classify cross-platform strict path evidence
prankster009 Jul 11, 2026
af7234b
test(lua2cpg): cover cross-platform r6 representative bridge regression
prankster009 Jul 11, 2026
d08b7b7
test(lua2cpg): target scoped cross-platform representative bridge fix…
prankster009 Jul 11, 2026
e0efcc8
test(lua2cpg): target cross-platform r5 representative bridge row
prankster009 Jul 11, 2026
194d368
fix(lua2cpg): preserve cross-platform representative bridge paths
prankster009 Jul 11, 2026
28386b1
test(lua2cpg): cover cross-platform r7 residual producer gaps
prankster009 Jul 11, 2026
9961258
test(lua2cpg): attribute cross-platform r7 residual families
prankster009 Jul 11, 2026
dc125cf
test(lua2cpg): establish r7 observability red baseline
prankster009 Jul 11, 2026
d361bbc
feat(lua2cpg): attribute r7 path performance
prankster009 Jul 11, 2026
b9d28ce
fix(lua2cpg): recover scoped miats exec sink
prankster009 Jul 12, 2026
d60da47
fix(lua2cpg): resolve captured require field calls
prankster009 Jul 12, 2026
6647db3
perf(lua2cpg): stop bridge search after strict path
prankster009 Jul 12, 2026
173eb6f
perf(lua2cpg): prune bridge flows before local search
prankster009 Jul 12, 2026
1a8e50d
fix(lua2cpg): recover XQSynchrodata strict path identity
prankster009 Jul 12, 2026
70ffe2d
fix(lua2cpg): recover requestMitv strict call result paths
prankster009 Jul 12, 2026
b8ca63d
fix(lua2cpg): recover setAllWifi strict conditional paths
prankster009 Jul 12, 2026
977fdea
fix(lua2cpg): recover deleteTransportList iterator bridge paths
prankster009 Jul 12, 2026
f3e3e6a
test(lua2cpg): cover pppoeStatus cross-platform path gap
prankster009 Jul 12, 2026
85ee044
test(lua2cpg): cover miats cross-platform path gap
prankster009 Jul 13, 2026
f429f43
fix(lua2cpg): preserve cross-platform sanitized bridge alternatives
prankster009 Jul 13, 2026
944a226
test(lua2cpg): cover vpnSwitch cross-platform path gap
prankster009 Jul 13, 2026
e552a89
test(lua2cpg): cover editDevice cross-platform path gap
prankster009 Jul 13, 2026
af2ef2b
fix(lua2cpg): recover scoped cross-platform editDevice path
prankster009 Jul 13, 2026
cc0978e
fix(lua2cpg): recover scoped cross-platform setRouterInfo paths
prankster009 Jul 13, 2026
c193b0a
fix(lua2cpg): recover scoped cross-platform setAllWifi band paths
prankster009 Jul 13, 2026
a283110
fix(lua2cpg): recover scoped cross-platform XQSynchrodata paths
prankster009 Jul 13, 2026
a512c4e
fix(lua2cpg): recover scoped cross-platform setRouterToBaidu paths
prankster009 Jul 13, 2026
08b8ca0
fix(lua2cpg): recover scoped cross-platform miats datacenter paths
prankster009 Jul 13, 2026
cbdc4db
fix(lua2cpg): recover scoped cross-platform setBaiduToRouter path
prankster009 Jul 13, 2026
6b8911f
fix(lua2cpg): recover scoped cross-platform getTransListFileStat path
prankster009 Jul 13, 2026
9cae865
fix(lua2cpg): recover scoped cross-platform tunnelSmartHomeRequest path
prankster009 Jul 13, 2026
67ab3df
fix(lua2cpg): recover scoped cross-platform tunnelSmartControllerRequ…
prankster009 Jul 13, 2026
d7ff9c5
fix(lua2cpg): recover scoped cross-platform setMeshInfo path
prankster009 Jul 13, 2026
2ed24f4
fix(lua2cpg): recover scoped cross-platform datacenter local exec path
prankster009 Jul 13, 2026
22d7488
fix(lua2cpg): recover scoped cross-platform setSysTime path
prankster009 Jul 13, 2026
7670e1e
fix(lua2cpg): recover scoped cross-platform webAccessControl path
prankster009 Jul 13, 2026
d5ff99e
fix(lua2cpg): resolve cross-platform module-global table field path
prankster009 Jul 13, 2026
d493a39
fix(lua2cpg): classify reference-analyzer real-firmware sanitizer hits
prankster009 Jul 15, 2026
8a40b73
test(lua2cpg): align cross-platform sanitizer guard with baseline
prankster009 Jul 15, 2026
89f70d3
fix(lua2cpg): preserve sanitizer call arguments
prankster009 Jul 15, 2026
6519ade
fix(lua2cpg): require requestMitv string.match sanitizer path
prankster009 Jul 15, 2026
c7ce06d
fix(lua2cpg): require setConfigIotDevHidessid _cmdformat sanitizer paths
prankster009 Jul 15, 2026
1ec9ceb
fix(lua2cpg): require addMeshNode _strformat sanitizer paths
prankster009 Jul 15, 2026
94ecb0e
fix(lua2cpg): require debug _cmdformat sanitizer paths
prankster009 Jul 15, 2026
9160b11
fix(lua2cpg): require apcli sanitizer path evidence
prankster009 Jul 15, 2026
39c5eb2
fix(lua2cpg): require setRouterToBaidu ipairs sanitizer path
prankster009 Jul 15, 2026
a86a72f
fix(lua2cpg): require xqsystem payment sanitizer paths
prankster009 Jul 15, 2026
bb5de1b
fix(lua2cpg): require XQAPModule apcli sanitizer paths
prankster009 Jul 15, 2026
e336796
fix(lua2cpg): require misystem setWifiAPMode sanitizer paths
prankster009 Jul 15, 2026
bcf7139
fix(lua2cpg): require XQSysUtil setSysTime sanitizer path
prankster009 Jul 15, 2026
be55ed1
fix(lua2cpg): require XQWifiUtil iwprivSetChannel sanitizer path
prankster009 Jul 16, 2026
f00ffe8
fix(lua2cpg): require pppoeStatus md5Str sanitizer bridge
prankster009 Jul 16, 2026
b198ae5
test(lua2cpg): align cumulative real-firmware contracts
prankster009 Jul 16, 2026
683ac26
fix(lua2cpg): place unresolved callee boundary precisely
prankster009 Jul 16, 2026
b709787
docs(lua2cpg): document reviewer usage path
prankster009 Jul 17, 2026
e6fca1e
docs(lua2cpg): remove external benchmark path
prankster009 Jul 17, 2026
c09a747
test(lua2cpg): remove external fixture references
prankster009 Jul 17, 2026
dbed7c4
test(lua2cpg): add openwrt-derived lua fixture corpus
prankster009 Jul 17, 2026
d868628
test(lua2cpg): limit openwrt fixture corpus to lua inputs
prankster009 Jul 17, 2026
0fdc001
test(lua2cpg): cover openwrt-derived fixture corpus
prankster009 Jul 17, 2026
17b0bd7
test(lua2cpg): replace vendor firmware tests with neutral corpus cove…
prankster009 Jul 17, 2026
4568003
docs(lua2cpg): document neutral firmware corpus
prankster009 Jul 17, 2026
18266e4
fix(lua2cpg): enforce luac bytecode input contract
prankster009 Jul 17, 2026
a9d87fe
fix(lua2cpg): generalize Lua module resolution
prankster009 Jul 17, 2026
de6c10d
fix(lua2cpg): derive local value flow generically
prankster009 Jul 17, 2026
af470d8
fix(lua2cpg): derive interprocedural bridges
prankster009 Jul 18, 2026
82001b3
fix(lua2cpg): classify sanitizers from resolved calls
prankster009 Jul 18, 2026
6cde944
test(lua2cpg): remove fixture-driven semantics
prankster009 Jul 18, 2026
ec7a540
fix(lua2cpg): require real vulnerability endpoints
prankster009 Jul 18, 2026
51afbb4
fix(lua2cpg): preserve call context in taint bridges
prankster009 Jul 18, 2026
0155c0b
fix(lua2cpg): preserve fixed table field provenance
prankster009 Jul 18, 2026
a4ed3df
fix(lua2cpg): merge reaching definitions at branches
prankster009 Jul 18, 2026
3d2e394
feat(lua2cpg): model conditional assignment dependence
prankster009 Jul 18, 2026
1866662
test(lua2cpg): update neutral corpus report expectations
prankster009 Jul 18, 2026
b64d7d6
docs(lua2cpg): align reviewer guidance with sanitized state
prankster009 Jul 18, 2026
9fbfd7e
style(lua2cpg): format test sources
prankster009 Jul 18, 2026
e81be43
chore(lua2cpg): keep generated analysis reports untracked
prankster009 Jul 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,4 @@ flake.lock
##############
user.bazelrc
bazel-*
/joern-cli/frontends/lua2cpg/src/test/resources/openwrt-derived-firmware-lua-report/
2 changes: 2 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ lazy val swiftsrc2cpg = Projects.swiftsrc2cpg
lazy val csharpsrc2cpg = Projects.csharpsrc2cpg
lazy val abap2cpg = Projects.abap2cpg
lazy val rust2cpg = Projects.rust2cpg
lazy val lua2cpg = Projects.lua2cpg
lazy val linterRules = Projects.linterRules

lazy val root = project
Expand All @@ -51,6 +52,7 @@ lazy val root = project
csharpsrc2cpg,
abap2cpg,
rust2cpg,
lua2cpg,
linterRules
)
.dependsOn(linterRules % ScalafixConfig)
Expand Down
2 changes: 2 additions & 0 deletions joern-cli/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ lazy val rubysrc2cpg = project.in(file("frontends/rubysrc2cpg"))
lazy val gosrc2cpg = project.in(file("frontends/gosrc2cpg"))
lazy val csharpsrc2cpg = project.in(file("frontends/csharpsrc2cpg"))
lazy val rust2cpg = project.in(file("frontends/rust2cpg"))
lazy val lua2cpg = project.in(file("frontends/lua2cpg"))

Universal / mappings ++= frontendMappings("kotlin2cpg", (kotlin2cpg / stage).value)
Universal / mappings ++= frontendMappings("abap2cpg", (abap2cpg / stage).value)
Expand All @@ -63,6 +64,7 @@ Universal / mappings ++= frontendMappings("rubysrc2cpg", (rubysrc2cpg / stage).v
Universal / mappings ++= frontendMappings("gosrc2cpg", (gosrc2cpg / stage).value)
Universal / mappings ++= frontendMappings("csharpsrc2cpg", (csharpsrc2cpg / stage).value)
Universal / mappings ++= frontendMappings("rust2cpg", (rust2cpg / stage).value)
Universal / mappings ++= frontendMappings("lua2cpg", (lua2cpg / stage).value)

lazy val cpgVersionFile = taskKey[File]("persist cpg version in file (e.g. for schema-extender)")
cpgVersionFile := {
Expand Down
218 changes: 218 additions & 0 deletions joern-cli/frontends/lua2cpg/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# lua2cpg

`lua2cpg` is a Lua 5.1 analyzer for Joern. It builds Code Property
Graphs for Lua programs through a bytecode-based pipeline and emits
taint-analysis evidence for Lua code, including interprocedural flow,
source/sink matches, sanitizer classifications, and vulnerability reports.

The analysis core operates on Lua 5.1 bytecode. To analyze Lua source files,
compile them with `luac5.1` and pass the generated `.luac` files to
`lua2cpg`. Source files placed in the input tree are also recorded in the CPG
file inventory.

## Prerequisites

- Use JDK 21 and `sbt` 1.12.5, matching the Joern repository configuration.
- Run the commands below from the Joern repository root.
- Install `luac5.1` when starting from Lua source files.

## Build

Build the staged frontend command:

```bash
sbt 'lua2cpg/stage'
```

The staged command is written to:

```bash
joern-cli/frontends/lua2cpg/target/universal/stage/bin/lua2cpg
```

Check the available options:

```bash
joern-cli/frontends/lua2cpg/target/universal/stage/bin/lua2cpg --help
```

## Quickstart

Analyze an existing Lua 5.1 bytecode directory:

```bash
LUA2CPG=joern-cli/frontends/lua2cpg/target/universal/stage/bin/lua2cpg
INPUT=/path/to/lua-bytecode
OUTPUT=/tmp/lua.cpg.bin

"$LUA2CPG" "$INPUT" --output "$OUTPUT"
```

Analyze a Lua source file by compiling it to Lua 5.1 bytecode first:

```bash
mkdir -p /tmp/lua-bytecode
luac5.1 -o /tmp/lua-bytecode/app.luac /path/to/app.lua

joern-cli/frontends/lua2cpg/target/universal/stage/bin/lua2cpg \
/tmp/lua-bytecode \
--output /tmp/lua.cpg.bin
```

For a source tree, preserve the directory layout while compiling:

```bash
SRC_ROOT=/path/to/lua-source
BC_ROOT=/tmp/lua-bytecode

mkdir -p "$BC_ROOT"
find "$SRC_ROOT" -name '*.lua' -print0 |
while IFS= read -r -d '' file; do
rel="${file#$SRC_ROOT/}"
out="$BC_ROOT/${rel%.lua}.luac"
mkdir -p "$(dirname "$out")"
luac5.1 -o "$out" "$file"
done

joern-cli/frontends/lua2cpg/target/universal/stage/bin/lua2cpg \
"$BC_ROOT" \
--output /tmp/lua.cpg.bin
```

## Inspecting The CPG

Open the generated CPG with Joern and inspect the Lua-specific evidence:

```bash
joern /tmp/lua.cpg.bin
```

Useful traversals:

```scala
cpg.metaData.language.l
cpg.file.name.l
cpg.method.fullName.l
cpg.call.nameExact("lua.module.resolution").code.l
cpg.call.nameExact("lua.calltarget.candidate").code.l
cpg.call.nameExact("lua.source.endpoint").code.l
cpg.call.nameExact("lua.sink.endpoint").code.l
cpg.call.nameExact("lua.sanitizer.classification").code.l
cpg.call.nameExact("lua.report.vulnerability").code.l
```

## Taint Evidence Export

`lua2cpg` can also write reviewer-visible JSON evidence for benchmark and
debugging workflows:

```bash
joern-cli/frontends/lua2cpg/target/universal/stage/bin/lua2cpg \
/path/to/lua-bytecode \
--output /tmp/lua.cpg.bin \
--lua-real-firmware-output-dir /tmp/lua2cpg-evidence
```

The evidence directory contains:

- `decoder-summary.json`: input, decode, prototype, instruction, callsite, and
local-flow totals.
- `path-search-profile.json`: taint path-search counters and retained pair
profiles.
- `run-summary.json`: native run status and decode totals.
- `run-errors.json`: native run errors.
- `staging/*.json`: per-artifact decode, flow, module-resolution, source/sink,
sanitizer, and path-evidence rows.

This export is optional. The primary `lua2cpg` output is the CPG written by
`--output`.

## Self-Contained Reviewer Corpus

The test resources include a self-contained OpenWrt-derived Lua corpus for
review and regression checks:

```text
joern-cli/frontends/lua2cpg/src/test/resources/openwrt-derived-firmware-lua/usr/lib/lua
```

The corpus preserves the original `usr/lib/lua` layout and contains:

- 42 `.lua` source files recorded in the CPG file inventory.
- 42 Lua 5.1 `.luac` bytecode files analyzed by the bytecode pipeline.

To generate a native JSON analysis report from the Joern repository root:

```bash
joern-cli/frontends/lua2cpg/target/universal/stage/bin/lua2cpg \
joern-cli/frontends/lua2cpg/src/test/resources/openwrt-derived-firmware-lua/usr/lib/lua \
--output /tmp/openwrt-derived-firmware-lua.cpg.bin \
--lua-real-firmware-output-dir /tmp/openwrt-derived-firmware-lua-report
```

The generated report and CPG are reproducible outputs and are intentionally not
tracked by Git. A successful corpus run decodes all 42 bytecode inputs with no
diagnostics and emits 164 source endpoints, 94 sink endpoints, 20 taint paths,
and 20 reports.

## Supported Analysis

- Lua version: Lua 5.1.
- Inputs: Lua 5.1 `.luac` bytecode; Lua source after compilation with
`luac5.1`.
- CPG content: file inventory, bytecode artifacts, prototypes, constants,
instructions, methods, identifiers, calls, and reaching definitions.
- Program analysis: intraprocedural value flow, module require/return-table
linkage, cross-module call targets, interprocedural argument and return flow,
source/sink matching, sanitizer classification, and vulnerability reports.
- Distribution boundary: this frontend does not ship QueryDB queries as part
of this README. Reviewer-visible results are exposed through CPG nodes and
optional JSON evidence.

## Architecture

The frontend is organized around a bytecode-first analysis pipeline:

- `LuaFileInventoryPass` records `.lua` source files in the CPG file inventory.
- `LuaBytecodeDecoder` decodes Lua 5.1 bytecode artifacts into profiles,
prototypes, constants, instructions, and diagnostics.
- `LuaBytecodeModelPass` emits the decoded bytecode model into the CPG.
- `LuaInstructionSemantics` computes prototype-local value, call, table,
global, upvalue, and boundary facts.
- `LuaProgramSemantics` normalizes module-level and interprocedural flow,
source/sink, sanitizer, and report evidence across decoded artifacts.
- `LuaRealFirmwareEvidenceExporter` writes the optional JSON evidence directory
requested by `--lua-real-firmware-output-dir`.

## Tests

Use the smallest tier that answers the review question first.

Quick smoke:

```bash
sbt 'lua2cpg/testOnly io.joern.lua2cpg.RulesSanitizerReportSmokeTest'
sbt 'lua2cpg/stage'
joern-cli/frontends/lua2cpg/target/universal/stage/bin/lua2cpg --help
git status --short
```

Focused capability tests:

```bash
sbt 'lua2cpg/testOnly io.joern.lua2cpg.BytecodeModelSmokeTest'
sbt 'lua2cpg/testOnly io.joern.lua2cpg.IntraproceduralSemanticsSmokeTest'
sbt 'lua2cpg/testOnly io.joern.lua2cpg.InterproceduralModuleTaintSmokeTest'
sbt 'lua2cpg/testOnly io.joern.lua2cpg.RulesSanitizerReportSmokeTest'
sbt 'lua2cpg/testOnly io.joern.lua2cpg.OpenWrtDerivedFirmwareCorpusSmokeTest'
sbt 'lua2cpg/testOnly io.joern.lua2cpg.RealFirmwareEvidenceExportSmokeTest'
```

Full frontend test suite:

```bash
sbt 'lua2cpg/test'
```

The full suite covers the decoder, CPG modeling, program semantics, evidence
export, and self-contained corpus regression tests.
13 changes: 13 additions & 0 deletions joern-cli/frontends/lua2cpg/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name := "lua2cpg"

dependsOn(
Projects.x2cpg % "compile->compile;test->test",
Projects.linterRules % ScalafixConfig
)

libraryDependencies ++= Seq(
"com.lihaoyi" %% "ujson" % Versions.upickle,
"org.scalatest" %% "scalatest" % Versions.scalatest % Test
)

enablePlugins(JavaAppPackaging, LauncherJarPlugin)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.joern.lua2cpg

import io.joern.lua2cpg.bytecode.{LuaProgramSemantics, LuaRealFirmwareEvidenceExporter}
import io.joern.lua2cpg.passes.{LuaBytecodeModelPass, LuaFileInventoryPass}
import io.joern.x2cpg.X2Cpg.withNewEmptyCpg
import io.joern.x2cpg.X2CpgFrontend
import io.joern.x2cpg.passes.frontend.MetaDataPass
import io.shiftleft.codepropertygraph.generated.Cpg

import scala.util.Try

class Lua2Cpg extends X2CpgFrontend {
override type ConfigType = Config
override val defaultConfig: Config = Config()

override def createCpg(config: Config): Try[Cpg] = {
val decoded = LuaBytecodeModelPass.decodeInputs(config)
val programSemantics = LuaProgramSemantics.normalize(decoded.map(item => item.relativeName -> item.result))
withNewEmptyCpg(config.outputPath, config) { (cpg, config) =>
new MetaDataPass(cpg, "LUA", config.inputPath).createAndApply()
new LuaFileInventoryPass(cpg, config).createAndApply()
new LuaBytecodeModelPass(cpg, config, Some(decoded)).createAndApply()
LuaRealFirmwareEvidenceExporter.write(config, decoded, programSemantics)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.joern.lua2cpg

import io.joern.lua2cpg.Frontend.cmdLineParser
import io.joern.x2cpg.{X2CpgConfig, X2CpgMain}
import scopt.OParser

final case class Config(
realFirmwareOutputDir: Option[String] = None,
override val genericConfig: X2CpgConfig.GenericConfig = X2CpgConfig.GenericConfig()
) extends X2CpgConfig[Config] {
override def withGenericConfig(value: X2CpgConfig.GenericConfig): Config =
copy(genericConfig = value)

def withRealFirmwareOutputDir(value: String): Config =
copy(realFirmwareOutputDir = Some(value))
}

private object Frontend {
val cmdLineParser: OParser[Unit, Config] = {
val builder = OParser.builder[Config]
import builder.*
OParser.sequence(
programName("lua2cpg"),
opt[String]("lua-real-firmware-output-dir")
.text("write Lua real-firmware benchmark evidence JSON to the given directory")
.action((value, config) => config.withRealFirmwareOutputDir(value))
)
}
}

object Main extends X2CpgMain(new Lua2Cpg(), cmdLineParser)
Loading