You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Replacing smartstring which is unmaintained, has UB and a restrictive license #816
In part of my miri testing of Rhai, I've discovered that the smartstring crate is unsound in general. After spending many hours tracking down the cause of the UB, I finally narrowed it down and found an issue report for the exact UB. The example I posted also introduces the same UB in Rhai when using the ImmutableString type. (Though it's not limited to my example)
I don't know what the exact unsound conditions for the UB are, but I'm sure someone has accidentally triggered it in Rhai (as I have as well).
The same UB mentioned in the issue below can also be triggered with a var.into() for ImmutableString in Rhai.
Since the last update for this crate was ~2 years ago, I have some doubts on whether the UB will ever be fixed. (Edit: Now archived, so definitely confirmed unmaintained) bodil/smartstring#49
Note, there IS a PR with the fix as far as I can tell, but the author seems to have been unresponsive to issues/PRs. This could be quickly patched by cloning the repo and using that one instead however
For any people who see this and want to fix the potential UB, see this PR for the fix, clone the repo and commit the fix, then place the following lines in your Cargo.toml:
[patch.crates-io]
smartstring = { git = "URL to your patched git repo" }
could let people opt-in to a safer implementation without a breaking change to the project, and without too much churn, and then if 2.0 appears one day, remove the old smartstring and be sound by default.
Thinking of swapping out smartstring, whether for another crate or for a fork, maybe doing something like
Yeah, I have been thinking about it, but smartstring has been working well so far with no particular issues. And unfortunately the SmartString type has been exposed in Rhai's public interface, so it is going to be a breaking change even if we move to a completely compatible crate...
And I haven't found one that works as well, except perhaps for ecow, but not sure how matured that one is...
changed the title [-]smartstring is unsound and has UB[/-][+]Replacing smartstring which is unmaintained, has UB and a restrictive license[/+]on Aug 12, 2026
I don't think you will be able to do a release to crates.io with that kind of dependency, usually crates.io requires all deps to be available through crates.io too.
The only public-facing change is the key type of rhai::Map, so if you'd prefer to land it in 2.0 rather than 1.x, I'm happy to retarget it.
Yes, this is my main concern. There are a number of public APIs with impl Into<SmartString> so there is no telling how much code it'd break.
Also we can consider changing SmartString (a type alias defined by Rhai) to compact_str... That may keep the changes minimal...
EDIT: Oh, mah bad.SmartString is an internal type alias, not exported.
Moving to 2.0 would be the safe choice. But then, since we're 2.0, we can consider other small breaking changes as well... Or maybe larger rearchitecture of the codebase...
the refcount is always atomic (also in non-sync builds
My concerns with ecow is exactly this: the Arc. Using it as a map key type will not affect things much as using SmartString would also be an allocation, but not ref counted.
The main concern is that ImmutableString is a single machine word right now, which is a shame if ecow is used and it bumps to two words... That would potentially make a lot of data types larger...
Thanks, that makes sense. And agreed on ecow: with ImmutableString at one word today, going to 16 bytes would grow every type that embeds it (Dynamic included), so that's not a good trade. I'd take ecow off the table for ImmutableString.
On how much the impl Into<Identifier> APIs would break, I compared the From impls. SmartString<LazyCompact> can be built from &str, &mut str, String, &String, Box<str> and Cow<str>. CompactString covers all of those except &mut str. The From<ImmutableString> / From<&ImmutableString> / From<Token> impls are Rhai's own and move over in #1175. So on those parameters, only callers passing a &mut str would stop compiling. The more visible change remains the key type of rhai::Map for code that names smartstring::SmartString explicitly.
Still, if you'd rather keep 1.x strictly stable, I'm happy to retarget #1175 to a 2.0 branch whenever there is one. Just let me know.
Sounds good, done. #1175 now adds an opt-in compact_str feature. Without it nothing changes; with it, Identifier and the key type of Map become CompactString. MSRV stays at 1.66, and there's a new compact_str row in the CI build matrix.
Note that smartstring remains a regular dependency until 2.0 (Cargo can't drop a dependency when a feature is enabled), so cargo deny/cargo audit will still list it in Cargo.lock until then.
Yes, I use AI to turn voice notes into written comments and to help edit the wording, including the PR description. The technical points are what I wanted to communicate, and I’m responsible for checking them and for the changes in the PR.
I can see why the polished wording made you ask. If anything I’ve written is unclear or technically wrong, please point it out and I’ll address it directly.
Activity
schungx commentedon Jan 18, 2024
There is a way to use a GitHub PR in
Cargo.toml...passcod commentedon Feb 25, 2026
Just to avoid a headscratcher, it's
/ref =/rev =/:Thinking of swapping out smartstring, whether for another crate or for a fork, maybe doing something like
could let people opt-in to a safer implementation without a breaking change to the project, and without too much churn, and then if 2.0 appears one day, remove the old smartstring and be sound by default.
schungx commentedon Feb 25, 2026
Yeah, I have been thinking about it, but smartstring has been working well so far with no particular issues. And unfortunately the
SmartStringtype has been exposed in Rhai's public interface, so it is going to be a breaking change even if we move to a completely compatible crate...And I haven't found one that works as well, except perhaps for
ecow, but not sure how matured that one is...chore(deps): accept the smartstring unmaintained advisory, and say why
[-]smartstring is unsound and has UB[/-][+]Replacing smartstring which is unmaintained, has UB and a restrictive license[/+]smartstringhas a less permissive license thanrhai; consider another crate #897schungx commentedon Aug 12, 2026
OK, we'll continue the
smartstringdiscussion on this issue, which is the first one raised.Any suggestions on which crate to replace it with? How about
compact_str?thalesfragoso commentedon Aug 12, 2026
I don't think you will be able to do a release to crates.io with that kind of dependency, usually crates.io requires all deps to be available through crates.io too.
fix(deps): ignore RUSTSEC-2026-0249 (smartstring unmaintained, via rh…
chore(deny): refresh the smartstring note and the duplicate baseline
chore(deny): refresh the smartstring note and the duplicate baseline
chore(deny): refresh the smartstring note and the duplicate baseline
chore(deny): refresh the smartstring note and the duplicate baseline
6 remaining items
schungx commentedon Sep 27, 2026
Yes, this is my main concern. There are a number of public APIs with
impl Into<SmartString>so there is no telling how much code it'd break.Also we can consider changing
SmartString(a type alias defined by Rhai) tocompact_str... That may keep the changes minimal...EDIT: Oh, mah bad.
SmartStringis an internal type alias, not exported.Moving to 2.0 would be the safe choice. But then, since we're 2.0, we can consider other small breaking changes as well... Or maybe larger rearchitecture of the codebase...
My concerns with
ecowis exactly this: theArc. Using it as a map key type will not affect things much as usingSmartStringwould also be an allocation, but not ref counted.The main concern is that
ImmutableStringis a single machine word right now, which is a shame ifecowis used and it bumps to two words... That would potentially make a lot of data types larger...hoppworks commentedon Sep 28, 2026
Thanks, that makes sense. And agreed on
ecow: withImmutableStringat one word today, going to 16 bytes would grow every type that embeds it (Dynamicincluded), so that's not a good trade. I'd takeecowoff the table forImmutableString.On how much the
impl Into<Identifier>APIs would break, I compared theFromimpls.SmartString<LazyCompact>can be built from&str,&mut str,String,&String,Box<str>andCow<str>.CompactStringcovers all of those except&mut str. TheFrom<ImmutableString>/From<&ImmutableString>/From<Token>impls are Rhai's own and move over in #1175. So on those parameters, only callers passing a&mut strwould stop compiling. The more visible change remains the key type ofrhai::Mapfor code that namessmartstring::SmartStringexplicitly.Still, if you'd rather keep 1.x strictly stable, I'm happy to retarget #1175 to a 2.0 branch whenever there is one. Just let me know.
schungx commentedon Sep 28, 2026
I suggest gating it under a new feature flag so that people with license restrictions can start using it.
In 2.0 we can remove the flag and make it the new default.
Gate compact_str behind an opt-in `compact_str` feature.
hoppworks commentedon Sep 28, 2026
Sounds good, done. #1175 now adds an opt-in
compact_strfeature. Without it nothing changes; with it,Identifierand the key type ofMapbecomeCompactString. MSRV stays at 1.66, and there's a newcompact_strrow in the CI build matrix.Note that
smartstringremains a regular dependency until 2.0 (Cargo can't drop a dependency when a feature is enabled), socargo deny/cargo auditwill still list it inCargo.lockuntil then.wensimehrp commentedon Sep 28, 2026
I'm sorry, but @hoppworks are you using AI to generate all the comments and the PR description???
hoppworks commentedon Sep 28, 2026
Yes, I use AI to turn voice notes into written comments and to help edit the wording, including the PR description. The technical points are what I wanted to communicate, and I’m responsible for checking them and for the changes in the PR.
I can see why the polished wording made you ask. If anything I’ve written is unclear or technically wrong, please point it out and I’ll address it directly.
schungx commentedon Sep 28, 2026
Nothing wrong with AI in my opinion. Just a tool which works fine if used well.
wensimehrp commentedon Sep 28, 2026
hoppworks commentedon Sep 28, 2026
I get that and AI does have a weird tone...
Replace unmaintained smartstring with compact_str.