Repository navigation
Open
Description
I have used afl.rs to fuzz all public API of thie crate. And I found several cases may cause panic.
The code to replay these panics are as follows:
These 6 cases are about arithmetic overflow.
let mut _local0 = unicode_segmentation::GraphemeCursor::new(18446742978509668351 ,18446744073709551615 ,false);
let _ = unicode_segmentation::GraphemeCursor::is_boundary(&mut (_local0), "t\u{7f}", 18446744073709551615);
let mut _local0 = unicode_segmentation::GraphemeCursor::new(18446707789825836799 ,18446744073709551615 ,false);
unicode_segmentation::GraphemeCursor::provide_context(&mut (_local0), "1", 18446744073709551615);
let mut _local0 = unicode_segmentation::GraphemeCursor::new(5404402016221612875 ,5425481077020773195 ,false);
let _ = unicode_segmentation::GraphemeCursor::prev_boundary(&mut (_local0), "KKK", 5425512962414627659);
let mut _local0 = unicode_segmentation::GraphemeCursor::new(18446744073709551615 ,8502796096475496447 ,false);
let _ = unicode_segmentation::GraphemeCursor::is_boundary(&mut (_local0), "\u{6dd}", 18446744073709551615);
let mut _local0 = unicode_segmentation::GraphemeCursor::new(5208492444341520456 ,5208492444341520431 ,true);
let _ = unicode_segmentation::GraphemeCursor::next_boundary(&mut (_local0), "HHHHHHHHHHHHH", 5208492589950978632);
let mut _local0 = unicode_segmentation::GraphemeCursor::new(18446744073709551615 ,16212958658533785599 ,false);
let _ = unicode_segmentation::GraphemeCursor::next_boundary(&mut (_local0), "0", 18446744073709551615);
These 2 cases are about utf-8 error and panicked at 'byte index is not a char boundary'.
let mut _local0 = unicode_segmentation::GraphemeCursor::new(8463800222054970741 ,8463951407229173877 ,false);
let _ = unicode_segmentation::GraphemeCursor::is_boundary(&mut (_local0), "Ë", 8463800222054970740);
let mut _local0 = unicode_segmentation::GraphemeCursor::new(5208492444341520467 ,3407250190757808200 ,true);
let _ = unicode_segmentation::GraphemeCursor::prev_boundary(&mut (_local0), "HHHZ\\HHH\0\u{e040}HHK", 5208492444341520456);
These 2 cases are about unwrap error.
let mut _local0 = unicode_segmentation::GraphemeCursor::new(2 ,2 ,true);
unicode_segmentation::GraphemeCursor::provide_context(&mut (_local0), "l ", 1);
let mut _local0 = unicode_segmentation::GraphemeCursor::new(4268070197446523707 ,4268070196469563392 ,false);
let _ = unicode_segmentation::GraphemeCursor::next_boundary(&mut (_local0), "; ", 4268070197446523705);
This case is about out-of-bound error.
let mut _local0 = unicode_segmentation::GraphemeCursor::new(4268070197446523713 ,4268070196471726080 ,false);
let _ = unicode_segmentation::GraphemeCursor::next_boundary(&mut (_local0), "\n\n\n\n\n\n\n\n", 4268070197446522939);
The simple bug report of this case is

I also placed the replay files at replay_files.
I hope you can check if these are real bugs need to be fixed. Thanks a lot.
Metadata
Metadata
Assignees
Labels
No labels
Activity
Manishearth commentedon Apr 5, 2023
Thanks! I don't have time to investigate this but would accept PRs for it!
In general the cursor APIs have a couple bugs
cardigan1008 commentedon Jul 28, 2024
For arithmetic overflow panics, I think we just need to wrap them with safer functions like
saturating_xto deal with these edge cases.I'll try to work on it.
fix(grapheme): harden two remaining fuzz panics from unicode-rs#119
TrueFurina commentedon Sep 16, 2026
The remaining panics from the fuzz cases here are now fixed on the branch of PR #183 (
fix/grapheme-cursor-offset-validation, commit 9f1c68e9):provide_context:chunk_start + chunk.len()overflowed with fuzzedchunk_startnearusize::MAX— nowsaturating_addprev_boundary: a desynchronizedoffsetbeyond the chunk sliced out-of-range — now clamped tochunk.len(), so the loop reportsPrevChunkas for any chunk without a preceding boundaryI reproduced case 2 and case 3 of this issue on 1.13.3 (the other three already panic differently / were fixed upstream) and all five repro cases pass on the PR branch, with the crate's full test suite still green (23 passed).
Also documenting here for anyone picking this up: the earlier suggestion of replacing arithmetic with
saturating_*covers the overflow class, but the out-of-range slice inprev_boundaryneeds the clamp (or an explicit range check) — it is a slicing panic, not an arithmetic one.fix: validate cursor offsets and pre-context chunk in GraphemeCursor …
Reject non-codepoint cursor offsets in is_boundary
Reject non-codepoint cursor offsets in is_boundary (#190)