Skip to content

[Code scan] Avoid data loss when loading repeated list and dict inputs #559

Description

@njzjz

This issue was found during a Codex global code scan of the repository.

Baseline commit: e3c5b38

Problem

The repeated list and dict loaders mutate repeat_jdata and then immediately read $refs before Vue has rendered the new repeated children. The repeated dict path also treats a dictionary as if it had obj.length.

Code references:

if (this.jdata.type.includes("list") && Array.isArray(obj)) {
if (this.jdata.repeat) {
this.repeat_jdata = [];
[...Array(obj.length).keys()].forEach((ii) => {
this.repeat_jdata.push(this.jdata);
});
[...Array(obj.length).keys()].forEach((ii) => {
var subobj = obj[ii];
if (this.$refs[`subitem_${ii}`])
this.$refs[`subitem_${ii}`].forEach((vv) => {
// check if it exists, name and alias
if (vv.jdata.name in subobj) {
// exists
vv.load(subobj[vv.jdata.name]);
}
vv.jdata.alias.forEach((aa) => {
if (aa in subobj) vv.load(subobj[aa]);
});
if (vv.jdata.optional) {
vv.check = vv.jdata.name in subobj;
}
});
});

} else if (this.jdata.type.includes("dict") && this.jdata.repeat) {
this.repeat_jdata = [];
this.keys = Object.keys(obj);
[...Array(obj.length).keys()].forEach((ii) => {
this.repeat_jdata.push(this.jdata);
});
[...Array(obj.length).keys()].forEach((ii) => {
var subobj = obj[this.keys[ii]];
if (this.$refs[`subitem_${ii}`])
this.$refs[`subitem_${ii}`].forEach((vv) => {
// check if it exists, name and alias
if (vv.jdata.name in subobj) {
// exists
vv.load(subobj[vv.jdata.name]);
}
vv.jdata.alias.forEach((aa) => {
if (aa in subobj) vv.load(subobj[aa]);
});
if (vv.jdata.optional) {
vv.check = vv.jdata.name in subobj;
}
});
});

Relevant snippet:

this.keys = Object.keys(obj);
[...Array(obj.length).keys()].forEach((ii) => {
  this.repeat_jdata.push(this.jdata);
});

Impact

Loading an existing JSON file with repeated entries can skip rows or fail to populate nested fields. Saving after that can drop data from the imported configuration.

Suggested fix

For repeated dicts, iterate over Object.keys(obj) instead of obj.length. After resizing repeat_jdata, wait for Vue to render the new children, for example with nextTick, before walking $refs and loading nested values.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions