https://bugs.kde.org/show_bug.cgi?id=448087
Bug ID: 448087
Summary: rust-qt-binding-generator: Undefined Behaviour: One
can obtain a mutable reference to a Rust struct from
an immutable reference.
Product: rust-qt-binding-generator
Version: unspecified
Platform: Other
OS: All
Status: REPORTED
Severity: normal
Priority: NOR
Component: general
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
Created attachment 145205
--> https://bugs.kde.org/attachment.cgi?id=145205&action=edit
example code ready to run cargo build
SUMMARY
By storing the Emitter in a RefCell one can create a mutable reference to the
struct the Emitter is associated with while an arbitrary number of immutable
references to the same struct may exist. If I understand the Rustonomicon
correctly, such a transmutation from & to &mut violates Rust's aliasing rules
and is undefined behaviour.
Let's assume a minimal example (also attached in a build-ready form):
-------------------
bindings.json
{
"cppFile": "src/Bindings.cpp",
"rust": {
"dir": "rust",
"interfaceModule": "interface",
"implementationModule": "implementation"
},
"objects": {
"SomeQtObject" : {
"type" : "Object",
"properties" : {
"some_property" : {
"type" : "bool",
"write": true
}
}
}
}
}
-------------------
implementation.rs:
use interface::*;
pub struct SomeQtObject {
emit : SomeQtObjectEmitter,
emit2: std::cell::RefCell<SomeQtObjectEmitter>,
some_property: bool,
}
impl SomeQtObjectTrait for SomeQtObject {
fn new(mut emit: SomeQtObjectEmitter) -> SomeQtObject {
let emit2 = emit.clone();
SomeQtObject {
emit,
emit2 : std::cell::RefCell::new(emit2),
some_property: false,
}
}
fn emit(&mut self) -> &mut SomeQtObjectEmitter {
&mut self.emit
}
fn some_property(&self) -> bool {
self.emit2.borrow_mut().some_property_changed();
self.some_property
}
fn set_some_property(&mut self, value: bool) {
self.some_property = value;
self.emit.some_property_changed();
}
}
-------------------
OBSERVED RESULT
The above (and attached) example compiles fine in Rust, even though it contains
an emit() statement in SomeQtObject::some_property(&self). If on the QML (or
C++) side a call to SomeQtObject::set_some_property(&mut self, value: bool) is
connected to this signal, undefined behaviour is invoked, as (implicitly) &self
gets transmuted into &mut self.
EXPECTED RESULT
The safe API of the rust-qt-binding-generator should ideally make such a
construct impossible.
ADDITIONAL INFORMATION
This might be related to https://bugs.kde.org/show_bug.cgi?id=406178, but I
think it's a different issue.
I've been thinking a bit on how to possibly solve this, but it's a non-trivial
issue that might not be solvable without API or behaviour changes...
The best option I see would be to internally create QueuedConnections on the
QObject that delay the update notifications and therefore ensure that there
will be no Rust -> C++ -> Rust call stacks on the same object. (That would also
fix #406178.)
--
You are receiving this mail because:
You are watching all bug changes.