This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 4a609e7cc Differential Fuzzing (2/3): Check `PostgreSqlDialect`
against PostgreSQL's own grammar (#2563)
4a609e7cc is described below
commit 4a609e7cc0d73754f8f03e0bc4011aaf0d288782
Author: Luca Cappelletti <[email protected]>
AuthorDate: Wed Sep 23 21:19:51 2026 +0000
Differential Fuzzing (2/3): Check `PostgreSqlDialect` against PostgreSQL's
own grammar (#2563)
---
.clusterfuzzlite/Dockerfile | 2 ++
docs/fuzzing.md | 2 ++
fuzz/Cargo.toml | 8 +++++++
fuzz/fuzz_targets/fuzz_postgres_accepts.rs | 38 ++++++++++++++++++++++++++++++
4 files changed, 50 insertions(+)
diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile
index 579c99ad5..8eba3fdd6 100644
--- a/.clusterfuzzlite/Dockerfile
+++ b/.clusterfuzzlite/Dockerfile
@@ -16,6 +16,8 @@
# under the License.
FROM gcr.io/oss-fuzz-base/base-builder-rust
+# pg_query's build script runs bindgen, which needs libclang at build time
+RUN apt-get update && apt-get install -y --no-install-recommends libclang-dev
&& rm -rf /var/lib/apt/lists/*
COPY . $SRC/datafusion-sqlparser-rs
WORKDIR $SRC/datafusion-sqlparser-rs
COPY ./.clusterfuzzlite/build.sh $SRC/
diff --git a/docs/fuzzing.md b/docs/fuzzing.md
index 1714e06cd..7c56c0c77 100644
--- a/docs/fuzzing.md
+++ b/docs/fuzzing.md
@@ -33,6 +33,8 @@ rendered statement no longer parses.
`fuzz_sqlite_accepts` compiles the input with a bundled SQLite, without
running it, and fails when SQLite accepts SQL that `SQLiteDialect` rejects.
Name resolution errors such as a missing table still count as accepted once
SQLite has read the statement to its end.
+`fuzz_postgres_accepts` parses the input with PostgreSQL's own grammar through
`pg_query` and fails when PostgreSQL accepts SQL that `PostgreSqlDialect`
rejects.
+
ClusterFuzzLite runs continuous fuzzing. Every pull request fuzzes for 10
minutes in
`code-change` mode, a daily batch job grows the shared corpus stored on the
`clusterfuzzlite` branch, and a daily prune compacts it.
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
index 4242bf8ce..42c91742b 100644
--- a/fuzz/Cargo.toml
+++ b/fuzz/Cargo.toml
@@ -27,6 +27,7 @@ cargo-fuzz = true
[dependencies]
libfuzzer-sys = "0.4"
libsqlite3-sys = { version = "0.38", features = ["bundled"] }
+pg_query = "6.2"
sqlparser = { path = ".." }
# Prevent this from interfering with workspaces
@@ -53,3 +54,10 @@ path = "fuzz_targets/fuzz_sqlite_accepts.rs"
test = false
doc = false
bench = false
+
+[[bin]]
+name = "fuzz_postgres_accepts"
+path = "fuzz_targets/fuzz_postgres_accepts.rs"
+test = false
+doc = false
+bench = false
diff --git a/fuzz/fuzz_targets/fuzz_postgres_accepts.rs
b/fuzz/fuzz_targets/fuzz_postgres_accepts.rs
new file mode 100644
index 000000000..e387d8ae6
--- /dev/null
+++ b/fuzz/fuzz_targets/fuzz_postgres_accepts.rs
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#![no_main]
+
+use libfuzzer_sys::fuzz_target;
+use sqlparser::dialect::PostgreSqlDialect;
+use sqlparser::parser::{Parser, ParserError};
+
+fuzz_target!(|sql: &str| {
+ if sql.contains('\0') {
+ return;
+ }
+ let Ok(parsed) = pg_query::parse(sql) else {
+ return;
+ };
+ match Parser::parse_sql(&PostgreSqlDialect {}, sql) {
+ Ok(_) | Err(ParserError::RecursionLimitExceeded) => {}
+ Err(err) => panic!(
+ "PostgreSQL {} accepts SQL the PostgreSQL dialect rejects\n sql:
{sql:?}\n error: {err}",
+ parsed.protobuf.version
+ ),
+ }
+});
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]