freedreno/decode: try harder to not crash in disasm
[mesa.git] / src / freedreno / rnn / rnn.c
index d6ba6fa50052a5da62e0ef698c2988608ca87a14..d82d2a561b02bee61e86f9d519dd0fc9417dec70 100644 (file)
@@ -39,7 +39,6 @@
 #include <ctype.h>
 #include <stdio.h>
 #include "rnn.h"
-#include "rnn_path.h"
 #include "util.h"
 
 #include "util/u_debug.h"
@@ -124,9 +123,9 @@ static char *getattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
 
 static int getboolattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
        char *c = getattrib(db, file, line, attr);
-       if (!strcmp(c, "yes") || !strcmp(c, "1"))
+       if (!strcmp(c, "yes") || !strcmp(c, "1") || !strcmp(c, "true"))
                return 1;
-       if (!strcmp(c, "no") || !strcmp(c, "0"))
+       if (!strcmp(c, "no") || !strcmp(c, "0") || !strcmp(c, "false"))
                return 0;
        rnn_err(db, "%s:%d: invalid boolean value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name);
        return 0;
@@ -467,7 +466,7 @@ static struct rnndelem *trydelem(struct rnndb *db, char *file, xmlNode *node) {
                res->type = RNN_ETYPE_USE_GROUP;
                xmlAttr *attr = node->properties;
                while (attr) {
-                       if (!strcmp(attr->name, "name")) {
+                       if (!strcmp(attr->name, "ref")) {
                                res->name = strdup(getattrib(db, file, node->line, attr));
                        } else {
                                rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
@@ -481,6 +480,8 @@ static struct rnndelem *trydelem(struct rnndb *db, char *file, xmlNode *node) {
                return res;
        } else if (!strcmp(node->name, "stripe") || !strcmp(node->name, "array")) {
                struct rnndelem *res = calloc(sizeof *res, 1);
+               if (!strcmp(node->name, "array"))
+                       res->name = "";
                res->type = (strcmp(node->name, "stripe")?RNN_ETYPE_ARRAY:RNN_ETYPE_STRIPE);
                res->length = 1;
                res->file = file;
@@ -864,6 +865,54 @@ static char * find_file(const char *file_orig)
        return fname;
 }
 
+static int validate_doc(struct rnndb *db, xmlDocPtr doc, xmlNodePtr database)
+{
+       /* find the schemaLocation property: */
+       xmlAttrPtr attr = database->properties;
+       const char *schema_name = NULL;
+       char *schema_path;
+
+       while (attr) {
+               if (!strcmp(attr->name, "schemaLocation")) {
+                       xmlNodePtr data = attr->children;
+                       schema_name = data->content;
+                       /* we expect this to look like <namespace url> schema.xsd.. I think
+                        * technically it is supposed to be just a URL, but that doesn't
+                        * quite match up to what we do.. Just skip over everything up to
+                        * and including the first whitespace character:
+                        */
+                       while (schema_name && (schema_name[0] != ' '))
+                               schema_name++;
+                       schema_name++;
+                       break;
+               }
+       }
+
+       if (!schema_name) {
+               rnn_err(db, "could not find schema.  Missing schemaLocation?");
+               return 0;
+       }
+
+       schema_path = find_file(schema_name);
+       if (!schema_path) {
+               rnn_err(db, "%s: couldn't find database file. Please set the env var RNN_PATH.\n", schema_name);
+               return 0;
+       }
+
+       xmlSchemaParserCtxtPtr parser = xmlSchemaNewParserCtxt(schema_path);
+       xmlSchemaPtr schema = xmlSchemaParse(parser);
+       xmlSchemaValidCtxtPtr validCtxt = xmlSchemaNewValidCtxt(schema);
+       int ret = xmlSchemaValidateDoc(validCtxt, doc);
+
+       xmlSchemaFreeValidCtxt(validCtxt);
+       xmlSchemaFree(schema);
+       xmlSchemaFreeParserCtxt(parser);
+
+       free(schema_path);
+
+       return ret;
+}
+
 void rnn_parsefile (struct rnndb *db, char *file_orig) {
        int i;
        char *fname;
@@ -891,6 +940,10 @@ void rnn_parsefile (struct rnndb *db, char *file_orig) {
                        rnn_err(db, "%s:%d: wrong top-level tag <%s>\n", fname, root->line, root->name);
                } else {
                        xmlNode *chain = root->children;
+                       if (validate_doc(db, doc, root)) {
+                               rnn_err(db, "%s: database file has errors\n", fname);
+                               return;
+                       }
                        while (chain) {
                                if (chain->type != XML_ELEMENT_NODE) {
                                } else if (!trytop(db, fname, chain) && !trydoc(db, fname, chain)) {