diff options
author | Johannes Beisswenger <johannes.beisswenger@cetitec.com> | 2023-05-10 11:22:07 +0200 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2023-05-14 15:22:22 +1000 |
commit | ea3b9a1d2c5af56c602fbfb1585536d5b21cb874 (patch) | |
tree | f206dc14043cef3c390ebf69df926f5c1700557b | |
parent | b2b9671583e9b006e69ec7a748fa168ef0c9dd52 (diff) | |
download | device-tree-compiler-ea3b9a1d2c5af56c602fbfb1585536d5b21cb874.tar.gz |
checks: Fix crash in graph_child_address if 'reg' cell size != 1
If an endpoint node has a 'reg' property which consists of more than
one cell (4 bytes) and given that matching '#address-cells' and '#size-cells'
properties are specified on the port node an assertion is triggered in
check_graph_child_address() before the relevant diagnostic checks in
check_graph_reg() (called by check_graph_port() and check_graph_endpoint()) are executed.
The issue is fixed by making graph_child_address depend on the
graph_port and graph_endpoint checks.
Additionally the assertion can also be triggered if the length of the
'reg' property is less than 4 bytes e.g. by specifying
'reg = "a";'. In that case however other warnings are produced
highlighting the malformed property before dtc crashes.
Example dts file triggering the issue:
/dts-v1/;
/ {
bar: bar {
port {
bar_con: endpoint {
remote-endpoint = <&foo_con>;
};
};
};
foo {
port {
#address-cells = <1>;
#size-cells = <1>; // should always be 0
foo_con: endpoint@1 {
reg = <1 2>; // causes assertion failure instead of diagnostic
remote-endpoint = <&bar_con>;
};
};
};
};
Signed-off-by: Johannes Beisswenger <johannes.beisswenger@cetitec.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r-- | checks.c | 50 |
1 files changed, 25 insertions, 25 deletions
@@ -1785,31 +1785,6 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti, } WARNING(graph_nodes, check_graph_nodes, NULL); -static void check_graph_child_address(struct check *c, struct dt_info *dti, - struct node *node) -{ - int cnt = 0; - struct node *child; - - if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus) - return; - - for_each_child(node, child) { - struct property *prop = get_property(child, "reg"); - - /* No error if we have any non-zero unit address */ - if (prop && propval_cell(prop) != 0) - return; - - cnt++; - } - - if (cnt == 1 && node->addr_cells != -1) - FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary", - node->children->name); -} -WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes); - static void check_graph_reg(struct check *c, struct dt_info *dti, struct node *node) { @@ -1900,6 +1875,31 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti, } WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes); +static void check_graph_child_address(struct check *c, struct dt_info *dti, + struct node *node) +{ + int cnt = 0; + struct node *child; + + if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus) + return; + + for_each_child(node, child) { + struct property *prop = get_property(child, "reg"); + + /* No error if we have any non-zero unit address */ + if (prop && propval_cell(prop) != 0 ) + return; + + cnt++; + } + + if (cnt == 1 && node->addr_cells != -1) + FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary", + node->children->name); +} +WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes, &graph_port, &graph_endpoint); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &node_name_chars, &node_name_format, &property_name_chars, |