Skip to content

Implement gio::File::set_attribute #1713

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

fbrouille
Copy link
Contributor

No description provided.

gio/src/file.rs Outdated
&self,
attribute: &str,
type_: FileAttributeType,
value: FileAttributeTypeValue<T>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be type-system matching from the file attribute to the value type probably. If you e.g. pass a u32 where a u64 was expected this will read random stack memory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok I changed the implementation: an enum ensures value is coherent with type

gio/src/file.rs Outdated

impl From<i32> for FileAttributeTypeValue<i32> {
fn from(value: i32) -> Self {
Self(&value as *const _ as _, value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the others are unsound. You store a pointer to some random, temporary stack frame of this function in the FileAttributeValue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hope the new version is ok

@fbrouille fbrouille force-pushed the g_file_set_attribute branch 3 times, most recently from 91b8c29 to 2deef12 Compare May 5, 2025 07:35
gio/src/file.rs Outdated
.1,
),
};
Stash(s.as_ptr(), s)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you get the pointer into s (stored on this functions stack), then return (i.e. move) s and afterwards the pointer points to this stack frame still while s is somewhere else

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: return FileAttributeTypeValueStorage instead of Stash and then caller calls as_ptr() on the object stored on stack (no move)

#[derive(Debug)]
// checker-ignore-item
pub enum FileAttributeTypeValue<'a> {
Pointer(FileAttributeType, glib::ffi::gpointer),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows creating values of arbitrary pointers from safe code, which is probably not a good idea

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: FileAttributeTypeValue is now a public structure with a private field of type FileAttributeTypeValueInner which is crate private. FileAttributeTypeValue provides associated methods to create instances for different types. All are public except new_pointer() which is only accessible by the crate.

gio/src/file.rs Outdated
Self::ByteString(s) => s.as_ptr() as _,
Self::Boolean(s) => s as *const _ as _,
Self::Uint32(s) => *s as *const _ as _,
Self::Int32(s) => *s as *const _ as _,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more types instead of _ would make it clearer whether this is correct or not

Suggested change
Self::Int32(s) => *s as *const _ as _,
Self::Int32(s) => *s as *const i32 as _,

if that doesn't compile then the code is wrong

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

gio/src/file.rs Outdated

#[derive(Debug)]
// checker-ignore-item
pub enum FileAttributeTypeValue<'a> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would gone with a trait but this also works. Should probably have From<T> impls to easily convert from plain types to this

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could then also use impl Into<FileAttributeTypeValue> in the function.

Also I wonder if the same type could be used for the other file attribute API

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure: From<T> would imply guessing the attribute type from T. If a developer pass a value of wrong type, code will compile but inferring a wrong attribute type.
I think that developers should explicitly specify the attribute type: e.g. file.set_attribute("name", FileAttributeTypeValue::new_uint64(1), ...) which is less error prone.
And I think also that this type is useless for the other file attribute API because their names are very explicit (type is clearly indicated) and their signatures already constrain the value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not very different from object.set_property() and other such API though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, new implementation like in object.set_property()

@bilelmoussaoui
Copy link
Member

i guess you could also easily add https://docs.gtk.org/gio/method.FileInfo.set_attribute.html ?

@fbrouille fbrouille force-pushed the g_file_set_attribute branch from 2deef12 to ef65bb7 Compare May 7, 2025 16:04
@fbrouille
Copy link
Contributor Author

sure, when we'll be aligned

gio/src/file.rs Outdated
}

impl<O: IsA<File>> FileExtManual for O {}

#[derive(Debug)]
// checker-ignore-item
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

gio/src/file.rs Outdated
Comment on lines 1153 to 1157
// new_pointer is private to gio crate to not allow creating values of arbitrary pointers from safe code
#[allow(dead_code)] // TODO remove this allow attribute when new_pointer will be used by this crate
pub(crate) fn new_pointer(type_: FileAttributeType, ptr: glib::ffi::gpointer) -> Self {
Self(FileAttributeTypeValueInner::Pointer(type_, ptr))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would remove this and move the dead_code to the enum if clippy complains, can be added later if needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@fbrouille fbrouille force-pushed the g_file_set_attribute branch from ef65bb7 to e53d619 Compare May 7, 2025 20:03
gio/src/file.rs Outdated
}

impl<O: IsA<File>> FileExtManual for O {}

#[derive(Debug)]
pub struct FileAttributeTypeValue<'a>(FileAttributeTypeValueInner<'a>);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub struct FileAttributeTypeValue<'a>(FileAttributeTypeValueInner<'a>);
pub struct FileAttributeValue<'a>(FileAttributeValueInner<'a>);

the type seems a bit redundant to me, but no strong opinion

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

gio/src/file.rs Outdated
Self(FileAttributeTypeValueInner::Object(value.as_ref()))
}

pub fn new_stringv(value: &'a Vec<&'a str>) -> Self {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also glib::collections::StrV or &[&str] or so that would work here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to &[&str] (cannot use &StrV because From<&StrV> conflicts with From<&Object>

gio/src/file.rs Outdated
Stringv(&'a Vec<&'a str>),
}

impl<'a> FileAttributeTypeValueInner<'a> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could merge the Inner and Storage, and on construction of the Inner just create whatever you need for passing it to C directly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@fbrouille fbrouille force-pushed the g_file_set_attribute branch from e53d619 to 7520fd3 Compare May 8, 2025 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants