diff options
| author | Peter Hutterer <peter.hutterer@who-t.net> | 2015-11-10 09:53:08 +1000 |
|---|---|---|
| committer | Pekka Paalanen <pekka.paalanen@collabora.co.uk> | 2015-11-17 14:36:21 +0200 |
| commit | f66e2d53dd8920451a4d9544b2fd2568a6a75b9b (patch) | |
| tree | 4feaf18a88235a2d9584405e9c8a34af7d6fc7f5 /src/scanner.c | |
| parent | protocol: add the new bitfields to the dtd (diff) | |
| download | wayland-f66e2d53dd8920451a4d9544b2fd2568a6a75b9b.tar wayland-f66e2d53dd8920451a4d9544b2fd2568a6a75b9b.tar.gz wayland-f66e2d53dd8920451a4d9544b2fd2568a6a75b9b.tar.bz2 wayland-f66e2d53dd8920451a4d9544b2fd2568a6a75b9b.tar.lz wayland-f66e2d53dd8920451a4d9544b2fd2568a6a75b9b.tar.xz wayland-f66e2d53dd8920451a4d9544b2fd2568a6a75b9b.tar.zst wayland-f66e2d53dd8920451a4d9544b2fd2568a6a75b9b.zip | |
Validate the protocol xml during scanning
Embed the wayland.dtd protocol data into the scanner binary so we can validate
external protocol files without requiring makefile changes. Hat-tip to Pekka
Paalanen for the embedding trick.
The embedding trick doesn't work well if the to-be-embedded file is in a
different location than the source file, so copy/link it during configure and
then build it in from the local directory.
The current expat parser is not a validating parser, moving scanner.c to
another parser has the risk of breaking compatibility. This patch adds libxml2
as extra (optional) dependency, but that also requires parsing the input
twice.
If the protocol fails validation a warning is printed but no error is returned
otherwise.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Diffstat (limited to 'src/scanner.c')
| -rw-r--r-- | src/scanner.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/scanner.c b/src/scanner.c index 8ecdd56..406519f 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -25,6 +25,8 @@ * SOFTWARE. */ +#include "config.h" + #include <stdbool.h> #include <stdio.h> #include <stdarg.h> @@ -34,9 +36,18 @@ #include <expat.h> #include <getopt.h> #include <limits.h> +#include <unistd.h> + +#if HAVE_LIBXML +#include <libxml/parser.h> +#endif #include "wayland-util.h" +/* Embedded wayland.dtd file, see dtddata.S */ +extern char DTD_DATA_begin; +extern int DTD_DATA_len; + enum side { CLIENT, SERVER, @@ -59,6 +70,57 @@ usage(int ret) exit(ret); } +static bool +is_dtd_valid(FILE *input) +{ + bool rc = true; +#if HAVE_LIBXML + xmlParserCtxtPtr ctx = NULL; + xmlDocPtr doc = NULL; + xmlDtdPtr dtd = NULL; + xmlValidCtxtPtr dtdctx; + xmlParserInputBufferPtr buffer; + int fd = fileno(input); + + dtdctx = xmlNewValidCtxt(); + ctx = xmlNewParserCtxt(); + if (!ctx || !dtdctx) + abort(); + + buffer = xmlParserInputBufferCreateMem(&DTD_DATA_begin, + DTD_DATA_len, + XML_CHAR_ENCODING_UTF8); + if (!buffer) { + fprintf(stderr, "Failed to init buffer for DTD.\n"); + abort(); + } + + dtd = xmlIOParseDTD(NULL, buffer, XML_CHAR_ENCODING_UTF8); + if (!dtd) { + fprintf(stderr, "Failed to parse DTD.\n"); + abort(); + } + + doc = xmlCtxtReadFd(ctx, fd, "protocol", NULL, 0); + if (!doc) { + fprintf(stderr, "Failed to read XML\n"); + abort(); + } + + rc = xmlValidateDtd(dtdctx, doc, dtd); + xmlFreeDoc(doc); + xmlFreeParserCtxt(ctx); + xmlFreeValidCtxt(dtdctx); + /* xmlIOParseDTD consumes buffer */ + + if (lseek(fd, 0, SEEK_SET) != 0) { + fprintf(stderr, "Failed to reset fd, output would be garbage.\n"); + abort(); + } +#endif + return rc; +} + #define XML_BUFFER_SIZE 4096 struct location { @@ -1617,6 +1679,15 @@ int main(int argc, char *argv[]) ctx.protocol = &protocol; ctx.loc.filename = "<stdin>"; + if (!is_dtd_valid(input)) { + fprintf(stderr, + "*******************************************************\n" + "* *\n" + "* WARNING: XML failed validation against built-in DTD *\n" + "* *\n" + "*******************************************************\n"); + } + /* create XML parser */ ctx.parser = XML_ParserCreate(NULL); XML_SetUserData(ctx.parser, &ctx); |
