Repository navigation
Lift char codes as Java chars when the query only holds Java chars - #99
Open
nils-loose wants to merge 1 commit into
Open
nils-loose wants to merge 1 commit into
nils-loose wants to merge 1 commit into
Conversation
Int2BvLifting took str.to_code in [-1, 0x10FFFF], so the 16-bit view of a char code needed a mod 65536 that makes Z3 slow on charAt comparisons. The executor encodes a Java string with one SMT char per UTF-16 char, so in a query whose string constants and str.from_code arguments are all at most 0xFFFF, every char code of a realisable model is at most 0xFFFF as well (string variables hold Java strings). For such queries (java_chars_only) the char code range is now [-1, 0xFFFF], which needs no mod, and lift_query adds str.to_code(x) <= 0xFFFF for each char code the rewrite relied on, so the lifted query is equivalent to the original one under these bounds. Queries with a char above 0xFFFF (e.g. a literal with a surrogate pair, which JavaSMT's makeString joins into one SMT char) or a str.from_code of an int code point keep the full range. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Full campaign: 1713 SV-COMP jobs (300 s CPU, no SA, sv-comp.cfg, 15 GB / -Xmx12g), dev 209cc0e and
Attribution: the 20 runs that changed were re-run with each change switched off ( This PR: no verdict changes (without it, the 20 changed runs give the same verdicts). CPU on runs with the same decided verdict, combined with #96: securibench -16%, autostub -19%, java-ranger-regression -44%; not separated from #96. 🤖 Generated with Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Int2BvLiftingtakesstr.to_codein[-1, 0x10FFFF](Z3's char range), so a lifted charAt comparison needs a(t + 32768) mod 65536 - 32768-style wrap, which makes Z3 slow on char-code queries.Changes
java_chars_only), char codes are lifted with range[-1, 0xFFFF], which needs nomod.lift_queryaddsstr.to_code(x) <= 0xFFFFfor each char code the rewrite relied on (as it already does for string lengths), so the lifted query is equivalent to the original one under these bounds and its models are models of the original.java_chars_only(iterative, memoised) rejects a query if a string constant (incl. regex range endpoints) has a char above 0xFFFF, if astr.from_codeargument's range exceeds 0xFFFF, or if it contains a Char-sorted term or a quantifier. Such queries keep the previous full-range lifting (separate cached instance).MAX_CHAR_CODE = 0xFFFF. That is not sound in general:makeStringiterates code points, so"😀"becomes one SMT char\u{1f600}(StringValue.java:48, a separate pre-existing encoding issue);str.from_codeof an int code point (StringValue.codePointString, indexOf(int));StringValue.getBounds) is only added for registered inputs, not for symbolic returns/fields orString[]elements.Soundness
Take any Java execution of the path and assign each SMT string variable the UTF-16 units of its Java value (this is the executor's model of charAt =
to_code(str.at)). Under the guard, every char in the query comes from such a variable, from a constant <= 0xFFFF, fromstr.from_codeof an argument <= 0xFFFF (withto_codetaken as <= 0xFFFF by induction over the term) or fromstr.from_intdigits; every other string operation only copies chars. So that assignment satisfies every added bound, and the bounds exclude only models no Java execution can realise. The argument does not depend on the executor's input bound. Retry constraints (extra_exprs) are not lifted and only remove models, as before.Measured
indexOf(int)) fall back to the full-range lifting.tests/test_int2bv_lifting.py(lift equivalence under BMP and supplementary assignments, incl. a mutation-checked test that fails without the added bound; guard cases; selection inlift_int2bv). Explorer suite: 212 passed (dev: 200 passed, 6 skipped).Full-campaign numbers follow in a comment.
🤖 Generated with Claude Code