diff options
-rw-r--r-- | Makefile.am | 11 | ||||
-rw-r--r-- | configure.ac | 13 | ||||
-rw-r--r-- | src/dtddata.S | 40 | ||||
-rw-r--r-- | src/scanner.c | 71 |
4 files changed, 132 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index 9114d98..7d31a39 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,11 +23,16 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = bin_PROGRAMS = wayland-scanner -wayland_scanner_SOURCES = src/scanner.c -wayland_scanner_CFLAGS = $(EXPAT_CFLAGS) $(AM_CFLAGS) -wayland_scanner_LDADD = $(EXPAT_LIBS) libwayland-util.la +wayland_scanner_SOURCES = src/scanner.c src/dtddata.S +wayland_scanner_CFLAGS = $(EXPAT_CFLAGS) $(LIBXML_CFLAGS) $(AM_CFLAGS) +wayland_scanner_LDADD = $(EXPAT_LIBS) $(LIBXML_LIBS) libwayland-util.la pkgconfig_DATA += src/wayland-scanner.pc +src/dtddata.o: protocol/wayland.dtd + +%.o: %.S + $(AM_V_GEN)$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c -o $@ $< + if USE_HOST_SCANNER wayland_scanner = wayland-scanner else diff --git a/configure.ac b/configure.ac index ef26929..48658cf 100644 --- a/configure.ac +++ b/configure.ac @@ -28,6 +28,7 @@ AM_SILENT_RULES([yes]) AC_PROG_CC AC_PROG_CXX AC_PROG_GREP +AM_PROG_AS # check if we have C++ compiler. This is hacky workaround, # for a reason why it is this way see @@ -71,6 +72,12 @@ AC_ARG_ENABLE([documentation], [], [enable_documentation=yes]) +AC_ARG_ENABLE([dtd-validation], + [AC_HELP_STRING([--disable-dtd-validation], + [Disable DTD validation of the protocol])], + [], + [enable_dtdvalidation=yes]) + AM_CONDITIONAL(USE_HOST_SCANNER, test "x$with_host_scanner" = xyes) AM_CONDITIONAL(ENABLE_LIBRARIES, test "x$enable_libraries" = xyes) @@ -105,6 +112,12 @@ PKG_CHECK_MODULES(EXPAT, [expat], [], AC_SUBST(EXPAT_LIBS) ]) +if test "x$enable_dtdvalidation" = "xyes"; then + PKG_CHECK_MODULES(LIBXML, [libxml-2.0]) + AC_DEFINE(HAVE_LIBXML, 1, [libxml-2.0 is available]) + AC_CONFIG_LINKS([src/wayland.dtd.embed:protocol/wayland.dtd]) +fi + AC_PATH_PROG(XSLTPROC, xsltproc) AM_CONDITIONAL([HAVE_XSLTPROC], [test "x$XSLTPROC" != "x"]) diff --git a/src/dtddata.S b/src/dtddata.S new file mode 100644 index 0000000..53debf3 --- /dev/null +++ b/src/dtddata.S @@ -0,0 +1,40 @@ +/* + * Copyright © 2015 Collabora, Ltd. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* from: http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967#comment-348129 */ + +.altmacro +.macro binfile name file + .p2align 2 + .globl \name&_begin +\name&_begin: + .incbin \file +\name&_end: + .byte 0 + .p2align 2 + .globl \name&_len +\name&_len: + .int (\name&_end - \name&_begin) +.endm + +.section .rodata +binfile DTD_DATA "src/wayland.dtd.embed" 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); |