- Scheme 62.2%
- Shell 15.6%
- C 14.7%
- Makefile 7.3%
- Common Lisp 0.2%
| .builds | ||
| .jerboa | ||
| docs | ||
| scripts | ||
| src/jerboa-pcre2 | ||
| support | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| jerboa_pcre2_shim.c | ||
| jpkg.sexp | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| SECURITY.md | ||
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-8development headers and librarypkg-configrecommended
On Debian/Ubuntu:
sudo apt-get install build-essential pkg-config libpcre2-dev
Build And Test
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
(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.