~ober/jerboa-pcre2
Imported from ~/mine/jerboa-pcre2
about
# jerboa-pcre2
PCRE2 bindings for Jerboa.
Status: experimental. Treat this repository as a native FFI and hostile-input
regular expression component until the release gates in `SECURITY.md` and
`docs/ffi-boundary.md` are complete.
## Requirements
- Jerboa `jerbuild`
- C compiler
- `libpcre2-8` development headers and library
- `pkg-config` recommended
On Debian/Ubuntu:
```sh
sudo apt-get install build-essential pkg-config libpcre2-dev
```
## Build And Test
```sh
make test
make native-sanitizer-test
make hostile-regex-corpus
make audit
make pcre2-advisory-check
make reproducibility-report
make target-evidence
make release-evidence
```
`make test` builds `jerboa_pcre2_shim`, transpiles the Jerboa libraries, and
runs the PCRE2 regression, concurrent lifecycle, and native-loader policy
tests. If `jerbuild` is not installed, the Makefile bootstraps the pinned
Jerboa release into `.jerboa/bin`.
Dynamic development builds must explicitly set `JERBOA_PCRE2_DEV_NATIVE=1`
and set `JERBOA_PCRE2_LIB` to an absolute trusted directory containing
`jerboa_pcre2_shim.so` or `jerboa_pcre2_shim.dylib`. Relative paths, symlinked
directory components, unexpected owners, world-writable paths, disallowed
group-writable paths, current-directory lookup, and bare-name lookup are
rejected by the shared `(std native-loader)` policy. Explicit development mode
permits group-write only for components owned by the same unprivileged user.
Privileged processes ignore both development variables. Production builds
should statically link the shim;
statically linked hosts are detected from their registered PCRE2 shim symbol
and do not need either environment variable.
`make native-sanitizer-test` runs UBSan everywhere and ASan/TSan on Linux.
The current Apple sanitizer runtimes do not enter `main` reliably on this
macOS release, so Darwin builds compile those instrumented binaries and print
an explicit skip; Linux CI remains the required ASan/TSan execution gate.
`make hostile-regex-corpus` runs an expanded deterministic adversarial-pattern
corpus under low PCRE2 match/depth limits and records fail-closed behavior for
backtracking-heavy and quoted-literal shapes.
`make audit` records the PCRE2 version and native linkage for release notes.
`make release-evidence` writes the local release artifact bundle under
`dist/release-evidence/`, including toolchain identity, native linkage, a
minimal SBOM manifest, hostile-regex corpus output, PCRE2 advisory status,
source inputs, hashes, and a two-clean-build reproducibility report that also
compares repeated corpus output.
Production support is blocked until `make target-evidence` records a
marker-complete proof through `JPCRE2_TARGET_PROOF_FILE`; production release
hosts should set `JPCRE2_REQUIRE_TARGET_PROOF=1`. The proof covers target PCRE2
advisory/linkage review, platform CVE/backport review, hostile-regex soak,
downstream consumer integration, external regex/FFI review, and cross-platform
smoke. It must not contain private pattern corpora, secrets, private paths,
hostnames, or raw command output.
## Usage
```scheme
(import (jerboa-pcre2 pcre2))
(define rx (pcre2-compile "(?P<year>\\d{4})-(?P<month>\\d{2})"))
(define m (pcre2-search rx "Today is 2026-06"))
(pcre-match-group m 0) ; => "2026-06"
(pcre-match-named m "year") ; => "2026"
(pcre2-release! rx)
```
PCRE2 is a backtracking engine. For untrusted patterns, set conservative match
limits with `(pcre2-set-match-limits! match-limit depth-limit)` and use an
admission/review step before running user-authored regular expressions.
Compiled regex objects may be shared between threads: match data and
substitution results are per operation, and `pcre2-release!` synchronizes with
in-flight native calls. New calls fail after release.
## API
| Function | Description |
| --- | --- |
| `(pcre2-compile pattern [options] [jit?])` | Compile a PCRE2 pattern |
| `(pcre2-regex pattern keyword: value ...)` | Compile with named options |
| `(pcre2-match rx subject [start])` | Full anchored match |
| `(pcre2-search rx subject [start])` | Unanchored search |
| `(pcre2-matches? rx subject [start])` | Boolean search |
| `(pcre-match-group m [n])` | Return group string or `#f` |
| `(pcre-match-named m name)` | Return named group |
| `(pcre-match-positions m [n])` | Return `(start . end)` |
| `(pcre2-replace rx subject replacement [start] [extended?])` | Replace first match |
| `(pcre2-replace-all rx subject replacement [start] [extended?])` | Replace all matches |
| `(pcre2-find-all rx subject [start])` | Return all match objects |
| `(pcre2-extract rx subject [start])` | Return matched strings |
| `(pcre2-fold rx kons knil subject [start])` | Fold over matches |
| `(pcre2-split rx subject [limit])` | Split by pattern |
| `(pcre2-partition rx subject)` | Alternating non-match/match list |
| `(pcre2-set-match-limits! match depth)` | Set per-thread PCRE2 match/depth limits |
| `(pcre2-quote str)` | Escape metacharacters |
| `(pcre2-release! rx)` | Free native resources |
Pregexp-compatible helpers are also provided:
`pcre2-pregexp-match`, `pcre2-pregexp-match-positions`,
`pcre2-pregexp-replace`, `pcre2-pregexp-replace*`, and
`pcre2-pregexp-quote`.
## Security
See `SECURITY.md`, `docs/ffi-boundary.md`,
`docs/pcre2-advisory-review.md`, and `docs/release-evidence.md`.
recent commits
- Document local mine repository authority 088a959 Jaime Fournier
- Update jpkg metadata for Forgejo 92816cf Jaime Fournier
- docs: remove jerboa-emacs restriction ebba3f0 Jaime Fournier
- Remove GitHub workflow metadata e0f7441 Jaime Fournier
- update AGENTS.md 00ed6cb Jaime Fournier
- docs: note ~/.local/bin/jerboa path in AGENTS.md f3273f2 Jaime Fournier
- Unify AGENTS.md with canonical jerboa version f622991 Jaime Fournier
- Skip substring copy in pregexp-match for unanchored patterns 1e94abb Jaime Fournier
- Build one UTF-8 byte/char offset table per subject 178422c Jaime Fournier
- Cache one match context per thread in the PCRE2 shim 2d0a8d8 Jaime Fournier