Bug 392959 - Invalid QString conversion in TreeModel.data.fieldname
Summary: Invalid QString conversion in TreeModel.data.fieldname
Status: RESOLVED FIXED
Alias: None
Product: rust-qt-binding-generator
Classification: Developer tools
Component: general (show other bugs)
Version: unspecified
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Jos van den Oever
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-04-10 09:04 UTC by kdebuac.rhn
Modified: 2018-05-13 13:38 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments
Workaround (934 bytes, patch)
2018-04-12 15:05 UTC, kdebuac.rhn
Details

Note You need to log in before you can comment on or make changes to this bug.
Description kdebuac.rhn 2018-04-10 09:04:06 UTC
Trying to implement an object backing a tree model, I found that QString contents of a requested field (Bookmarks::data() -> String) were passed in an invalid way across the C/C++ boundary.

The issue was that interface::QString was converted wrong into qstring_t, with mismatched pointer dereferences.

The object in question:

"Bookmarks": {
            "type": "Tree",
            "itemProperties": {
                "type_": {
                    "type": "quint32",
                    "roles": [ ["toolTip"] ]
                },
                "name": {
                    "type": "QString",
                    "roles": [ ["display"] ]
                },
                "count": {
                    "type": "quint32",
                    "roles": [ [], ["display"] ]
                }
            }
        }

The affected field was `name`, thus the invalid function to read it:

#[no_mangle]
pub unsafe extern "C" fn bookmarks_data_name(
    ptr: *const Bookmarks, item: usize,
    d: *mut c_void,
    set: fn(*mut c_void, QString),
) {
    let data = (&*ptr).name(item);
    set(d, (data).into());
}

The fixed function:

#[no_mangle]
pub unsafe extern "C" fn bookmarks_data_name(
    ptr: *const Bookmarks, item: usize,
    d: *mut c_void,
    set: fn(*mut c_void, &QString), // added pointer
) {
    let data = (&*ptr).name(item);
    let qs = (data).into();
    set(d, &qs); // should be safe; a copy is made on the other side
}

The code to generate this is around line 360 in src/rust.cpp. The other side is line 932 in src/cpp.cpp
Comment 1 kdebuac.rhn 2018-04-12 15:05:35 UTC
Created attachment 111974 [details]
Workaround

This works around the issue, and fixes failing test cases. Untested with rustByValue.
Comment 2 kdebuac.rhn 2018-04-12 15:09:31 UTC
I'm not sure if the patch is actually the right place to tackle this problem.

I would try to fix the behaviour of "rustByValue", but the way it's used seems opposite to me and I dare not touch it:

{
    let data = (&*ptr).%3();
    set(p, %5data.into());
}
)").arg(o.name, base, snakeCase(p.name), p.type.name,
                p.rustByValue ?"&" :"");

In the above snippet, the generated code will use a *reference* &data.into() iff rustByValue is *true*. Is this reversed?
Comment 3 Jos van den Oever 2018-05-13 13:38:14 UTC
This issue is fixed as of 57d557378ee629496b4a6afc58022f0677cdff06. The struct qstring_t is not present anymore. QString data is now passed as two pieces of data: the pointer to the characters and the length.