Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl AsObjectArg <T> makes T-object free #835

Closed
egsam98 opened this issue Aug 3, 2024 · 4 comments · Fixed by #846
Closed

impl AsObjectArg <T> makes T-object free #835

egsam98 opened this issue Aug 3, 2024 · 4 comments · Fixed by #846
Labels
bug c: engine Godot classes (nodes, resources, ...) ub Undefined behavior

Comments

@egsam98
Copy link

egsam98 commented Aug 3, 2024

Hello, recently I've found suspicious behaviour in Godot runtime while using new pattern AsObjectArg in arguments. Godot prints error that object is null on such calls.
For example, I have a function that prints letter textures into RichTextLabel:

fn print(to: &mut Gd<RichTextLabel>, text: &str, font: Font) {
    to.clear();
    let font_pathf = match font {
        Font::Large => font_large_pathf,
        Font::Street => font_street_pathf,
    };
    for char in text.as_bytes() {
        let path = font_pathf(char.to_ascii_uppercase());
        match try_load::<Texture2D>(path) {
            Ok(img) => to.add_image(img),
            Err(err) => godot_error!("print to {}: {}", to, err),
        };
    }
}

Godot logs errors in editor with a reference to this line: https://github.com/godotengine/godot/blob/15073afe3856abd2aa1622492fe50026c7d63dc1/scene/gui/rich_text_label.cpp#L3228
Similar issue was noticed in other functions PhysicsDirectSpaceState3D::like get_rest_info etc.

Here is two options to resolve the issue:

  1. Clone a reference counter: to.add_image(img.clone())
  2. Borrow: to.add_image(&img)

Is that behaviour expected?

@Bromeon
Copy link
Member

Bromeon commented Aug 3, 2024

No, that shouldn't happen.
You're saying that to.add_image(&img) instead of to.add_image(img) does not trigger the problem?

My current plan is to make all APIs accept references, for a few reasons:

  • To address #790
  • Consistency: all values that aren't Copy are passed by reference (Gd, Array, Dictionary, GString, Callable, ...)
  • It doesn't suggest that passing by value is more efficient ("move"), because it's not

So this would mean removing the value impls for AsObjectArg, which would "solve" this. But yes, it shouldn't happen in the first place 🙂

@egsam98
Copy link
Author

egsam98 commented Aug 3, 2024

Correct, to.add_image(&img) does NOT trigger it. Same for to.add_image(img.clone())

@egsam98
Copy link
Author

egsam98 commented Aug 4, 2024

Another error occurred today from PhysicsDirectSpaceState3D::intersect_shape(params):
https://github.com/godotengine/godot/blob/15073afe3856abd2aa1622492fe50026c7d63dc1/servers/physics_server_3d.cpp#L404
The only safe way is to replace args everywhere to their borrowed analogue in whole project

@Bromeon
Copy link
Member

Bromeon commented Aug 4, 2024

Thanks!

I think I see the problem -- it happens only for methods with default parameters:

// impl RichTextLabel

pub fn add_image(&mut self, image: impl AsObjectArg<crate::classes::Texture2D>) {
    self.add_image_ex(image).done()
}

pub fn add_image_ex(
    &mut self,
    image: impl AsObjectArg<crate::classes::Texture2D>, // <- local variable
) -> ExAddImage<'_> {
    ExAddImage::new(self, image.as_object_arg())
} // <- drop `image`!

pub struct ExAddImage<'a> {
    surround_object: &'a mut re_export::RichTextLabel,
    image: ObjectArg<crate::classes::Texture2D>, // <- only stores pointer
    ...
}

impl< 'a > ExAddImage< 'a > {
    fn new(surround_object: &'a mut re_export::RichTextLabel, image: ObjectArg<Texture2D>) -> Self {
        Self { surround_object, image, ... }
    }
}

I.e. use-after-free error.

For now, I'd recommend changing the calls to take borrows. As mentioned above, we'd likely enforce this soon, which would also address this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug c: engine Godot classes (nodes, resources, ...) ub Undefined behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants