Skip to content

Commit e88da37

Browse files
committed
Add gettext fuzz target
1 parent c40d5eb commit e88da37

File tree

6 files changed

+98
-21
lines changed

6 files changed

+98
-21
lines changed

.github/workflows/test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ jobs:
6161
cargo fuzz run normalize -- -only_ascii=1 -max_total_time=30
6262
cargo fuzz cmin normalize
6363
64+
- name: Run gettext fuzzer and minimize corpus
65+
run: |
66+
cd i18n-helpers
67+
cargo fuzz run gettext -- -only_ascii=1 -max_total_time=30
68+
cargo fuzz cmin normalize
69+
6470
clippy:
6571
name: Clippy
6672
runs-on: ubuntu-latest

i18n-helpers/fuzz/Cargo.lock

Lines changed: 18 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

i18n-helpers/fuzz/Cargo.toml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ publish = false
88
cargo-fuzz = true
99

1010
[dependencies]
11+
arbitrary = { version = "1.3.1", features = ["derive"] }
1112
libfuzzer-sys = "0.4.0"
13+
mdbook = { version = "0.4.25", default-features = false }
14+
mdbook-i18n-helpers = { path = ".." }
1215
polib = "0.2.0"
1316
pretty_assertions = "1.3.0"
1417

15-
[dependencies.mdbook-i18n-helpers]
16-
path = ".."
17-
1818
# Prevent this from interfering with workspaces
1919
[workspace]
2020
members = ["."]
@@ -33,3 +33,9 @@ name = "normalize"
3333
path = "fuzz_targets/normalize.rs"
3434
test = false
3535
doc = false
36+
37+
[[bin]]
38+
name = "gettext"
39+
path = "fuzz_targets/gettext.rs"
40+
test = false
41+
doc = false
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![no_main]
2+
3+
use libfuzzer_sys::fuzz_target;
4+
use mdbook_i18n_helpers::gettext::translate_book;
5+
use mdbook_i18n_helpers_fuzz::{create_book, create_catalog, BookItem};
6+
7+
fuzz_target!(|inputs: (Vec<(&str, &str)>, Vec<BookItem>)| {
8+
let (translations, book_items) = inputs;
9+
let catalog = create_catalog(translations);
10+
let mut book = create_book(book_items);
11+
translate_book(&catalog, &mut book)
12+
});

i18n-helpers/fuzz/fuzz_targets/normalize.rs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,9 @@
22

33
use libfuzzer_sys::fuzz_target;
44
use mdbook_i18n_helpers::normalize::normalize;
5-
use polib::catalog::Catalog;
6-
use polib::message::Message;
7-
use polib::metadata::CatalogMetadata;
5+
use mdbook_i18n_helpers_fuzz::create_catalog;
86

97
fuzz_target!(|translations: Vec<(&str, &str)>| {
108
let catalog = create_catalog(translations);
119
let _ = normalize(catalog);
1210
});
13-
14-
fn create_catalog(translations: Vec<(&str, &str)>) -> Catalog {
15-
let mut catalog = Catalog::new(CatalogMetadata::new());
16-
for (idx, (msgid, msgstr)) in translations.iter().enumerate() {
17-
let message = Message::build_singular()
18-
.with_source(format!("foo.md:{idx}"))
19-
.with_msgid(String::from(*msgid))
20-
.with_msgstr(String::from(*msgstr))
21-
.done();
22-
catalog.append_or_update(message);
23-
}
24-
catalog
25-
}

i18n-helpers/fuzz/src/lib.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use arbitrary::Arbitrary;
2+
use mdbook::book::{Book, Chapter};
3+
use polib::catalog::Catalog;
4+
use polib::message::Message;
5+
use polib::metadata::CatalogMetadata;
6+
use std::path::PathBuf;
7+
8+
/// Generate a random Catalog for fuzzing.
9+
pub fn create_catalog(translations: Vec<(&str, &str)>) -> Catalog {
10+
let mut catalog = Catalog::new(CatalogMetadata::new());
11+
for (idx, (msgid, msgstr)) in translations.iter().enumerate() {
12+
let message = Message::build_singular()
13+
.with_source(format!("foo.md:{idx}"))
14+
.with_msgid(String::from(*msgid))
15+
.with_msgstr(String::from(*msgstr))
16+
.done();
17+
catalog.append_or_update(message);
18+
}
19+
catalog
20+
}
21+
22+
/// Generate a random Book for fuzzing.
23+
pub fn create_book(book_items: Vec<BookItem>) -> Book {
24+
let mut book = Book::new();
25+
for item in book_items.into_iter() {
26+
book.push_item(item);
27+
}
28+
book
29+
}
30+
31+
/// Wrapper enum for generating arbitrary `BookItem`s.
32+
#[derive(Arbitrary, Debug)]
33+
pub enum BookItem {
34+
Chapter { name: String, content: String },
35+
Separator,
36+
PartTitle(String),
37+
}
38+
39+
impl From<BookItem> for mdbook::book::BookItem {
40+
fn from(other: BookItem) -> mdbook::book::BookItem {
41+
match other {
42+
BookItem::Chapter { name, content } => mdbook::book::BookItem::Chapter(Chapter::new(
43+
&name,
44+
content,
45+
PathBuf::new(),
46+
Vec::new(),
47+
)),
48+
BookItem::Separator => mdbook::book::BookItem::Separator,
49+
BookItem::PartTitle(title) => mdbook::book::BookItem::PartTitle(title),
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)