summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Beisswenger <johannes.beisswenger@cetitec.com>2023-05-10 11:22:07 +0200
committerDavid Gibson <david@gibson.dropbear.id.au>2023-05-14 15:22:22 +1000
commitea3b9a1d2c5af56c602fbfb1585536d5b21cb874 (patch)
treef206dc14043cef3c390ebf69df926f5c1700557b
parentb2b9671583e9b006e69ec7a748fa168ef0c9dd52 (diff)
downloaddevice-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.c50
1 files changed, 25 insertions, 25 deletions
diff --git a/checks.c b/checks.c
index 8ed7a60..c49ed51 100644
--- a/checks.c
+++ b/checks.c
@@ -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,