aboutsummaryrefslogtreecommitdiff
path: root/libpkgconf
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2017-09-19 17:21:01 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2017-09-19 17:22:11 +0300
commitdf3f033ad8586bb28503d204eac4e02990f64a44 (patch)
tree46edf90619a86d16cfaeaf12408e7fe486349e75 /libpkgconf
parent2ac205d1d0aaff43513471b0e185b8a9a2487d9a (diff)
Fix some escaping related issues
Diffstat (limited to 'libpkgconf')
-rw-r--r--libpkgconf/argvsplit.c7
-rw-r--r--libpkgconf/argvsplit.c.orig156
-rw-r--r--libpkgconf/fileio.c8
-rw-r--r--libpkgconf/fileio.c.orig120
4 files changed, 289 insertions, 2 deletions
diff --git a/libpkgconf/argvsplit.c b/libpkgconf/argvsplit.c
index 85f7f57..cb5844a 100644
--- a/libpkgconf/argvsplit.c
+++ b/libpkgconf/argvsplit.c
@@ -88,8 +88,15 @@ pkgconf_argv_split(const char *src, int *argc, char ***argv)
}
else
{
+ /*
+ * There is no reason to keep space character escaped in fragment
+ * objects, especially given that other characters are unescaped (issue
+ * #139 is reported).
+ */
+ /*
if (isspace((unsigned int) *src_iter))
*dst_iter++ = '\\';
+ */
*dst_iter++ = *src_iter;
}
diff --git a/libpkgconf/argvsplit.c.orig b/libpkgconf/argvsplit.c.orig
new file mode 100644
index 0000000..85f7f57
--- /dev/null
+++ b/libpkgconf/argvsplit.c.orig
@@ -0,0 +1,156 @@
+/*
+ * argvsplit.c
+ * argv_split() routine
+ *
+ * Copyright (c) 2012, 2017 pkgconf authors (see AUTHORS).
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * This software is provided 'as is' and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising
+ * from the use of this software.
+ */
+
+#include <libpkgconf/libpkgconf.h>
+
+/*
+ * !doc
+ *
+ * libpkgconf `argvsplit` module
+ * =============================
+ *
+ * This is a lowlevel module which provides parsing of strings into argument vectors,
+ * similar to what a shell would do.
+ */
+
+/*
+ * !doc
+ *
+ * .. c:function:: void pkgconf_argv_free(char **argv)
+ *
+ * Frees an argument vector.
+ *
+ * :param char** argv: The argument vector to free.
+ * :return: nothing
+ */
+void
+pkgconf_argv_free(char **argv)
+{
+ free(argv[0]);
+ free(argv);
+}
+
+/*
+ * !doc
+ *
+ * .. c:function:: int pkgconf_argv_split(const char *src, int *argc, char ***argv)
+ *
+ * Splits a string into an argument vector.
+ *
+ * :param char* src: The string to split.
+ * :param int* argc: A pointer to an integer to store the argument count.
+ * :param char*** argv: A pointer to a pointer for an argument vector.
+ * :return: 0 on success, -1 on error.
+ * :rtype: int
+ */
+int
+pkgconf_argv_split(const char *src, int *argc, char ***argv)
+{
+ char *buf = malloc(strlen(src) + 1);
+ const char *src_iter;
+ char *dst_iter;
+ int argc_count = 0;
+ int argv_size = 5;
+ char quote = 0;
+ bool escaped = false;
+
+ src_iter = src;
+ dst_iter = buf;
+
+ memset(buf, 0, strlen(src) + 1);
+
+ *argv = calloc(sizeof (void *), argv_size);
+ (*argv)[argc_count] = dst_iter;
+
+ while (*src_iter)
+ {
+ if (escaped)
+ {
+ /* POSIX: only \CHAR is special inside a double quote if CHAR is {$, `, ", \, newline}. */
+ if (quote == '\"')
+ {
+ if (!(*src_iter == '$' || *src_iter == '`' || *src_iter == '"' || *src_iter == '\\'))
+ *dst_iter++ = '\\';
+
+ *dst_iter++ = *src_iter;
+ }
+ else
+ {
+ if (isspace((unsigned int) *src_iter))
+ *dst_iter++ = '\\';
+
+ *dst_iter++ = *src_iter;
+ }
+
+ escaped = false;
+ }
+ else if (quote)
+ {
+ if (*src_iter == quote)
+ quote = 0;
+ else if (*src_iter == '\\')
+ escaped = true;
+ else
+ *dst_iter++ = *src_iter;
+ }
+ else if (isspace((unsigned int)*src_iter))
+ {
+ if ((*argv)[argc_count] != NULL)
+ {
+ argc_count++, dst_iter++;
+
+ if (argc_count == argv_size)
+ {
+ argv_size += 5;
+ *argv = realloc(*argv, sizeof(void *) * argv_size);
+ }
+
+ (*argv)[argc_count] = dst_iter;
+ }
+ }
+ else switch(*src_iter)
+ {
+ case '\\':
+ escaped = true;
+ break;
+
+ case '\"':
+ case '\'':
+ quote = *src_iter;
+ break;
+
+ default:
+ *dst_iter++ = *src_iter;
+ break;
+ }
+
+ src_iter++;
+ }
+
+ if (escaped || quote)
+ {
+ free(*argv);
+ free(buf);
+ return -1;
+ }
+
+ if (strlen((*argv)[argc_count]))
+ {
+ argc_count++;
+ }
+
+ *argc = argc_count;
+ return 0;
+}
diff --git a/libpkgconf/fileio.c b/libpkgconf/fileio.c
index d1c848f..bcc9c50 100644
--- a/libpkgconf/fileio.c
+++ b/libpkgconf/fileio.c
@@ -28,12 +28,16 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
while (s < end && (c = getc(stream)) != EOF)
{
- if (c == '\\')
+ /*
+ * Fix double-backslash swallowing (issue #140 is reported).
+ */
+ if (c == '\\' && !quoted)
{
quoted = true;
continue;
}
- else if (c == '#')
+
+ if (c == '#')
{
if (!quoted) {
/* Skip the rest of the line */
diff --git a/libpkgconf/fileio.c.orig b/libpkgconf/fileio.c.orig
new file mode 100644
index 0000000..d1c848f
--- /dev/null
+++ b/libpkgconf/fileio.c.orig
@@ -0,0 +1,120 @@
+/*
+ * fileio.c
+ * File reading utilities
+ *
+ * Copyright (c) 2012 pkgconf authors (see AUTHORS).
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * This software is provided 'as is' and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising
+ * from the use of this software.
+ */
+
+#include <libpkgconf/libpkgconf.h>
+
+char *
+pkgconf_fgetline(char *line, size_t size, FILE *stream)
+{
+ char *s = line;
+ char *end = line + size - 1;
+ bool quoted = false;
+ int c = '\0', c2;
+
+ if (s == NULL)
+ return NULL;
+
+ while (s < end && (c = getc(stream)) != EOF)
+ {
+ if (c == '\\')
+ {
+ quoted = true;
+ continue;
+ }
+ else if (c == '#')
+ {
+ if (!quoted) {
+ /* Skip the rest of the line */
+ do {
+ c = getc(stream);
+ } while (c != '\n' && c != EOF);
+ *s++ = c;
+ break;
+ }
+ quoted = false;
+ continue;
+ }
+ else if (c == '\n')
+ {
+ if (quoted)
+ {
+ /* Trim spaces */
+ do {
+ c2 = getc(stream);
+ } while (c2 == '\t' || c2 == ' ');
+
+ ungetc(c2, stream);
+
+ quoted = false;
+ continue;
+ }
+ else
+ {
+ *s++ = c;
+ }
+
+ break;
+ }
+ else if (c == '\r')
+ {
+ *s++ = '\n';
+
+ if ((c2 = getc(stream)) == '\n')
+ {
+ if (quoted)
+ {
+ quoted = false;
+ continue;
+ }
+
+ break;
+ }
+
+ ungetc(c2, stream);
+
+ if (quoted)
+ {
+ quoted = false;
+ continue;
+ }
+
+ break;
+ }
+ else
+ {
+ if (quoted) {
+ *s++ = '\\';
+ quoted = false;
+ }
+ *s++ = c;
+ }
+
+ }
+
+ if (c == EOF && (s == line || ferror(stream)))
+ return NULL;
+
+ *s = '\0';
+
+ /* Remove newline character. */
+ if (s > line && *(--s) == '\n') {
+ *s = '\0';
+
+ if (s > line && *(--s) == '\r')
+ *s = '\0';
+ }
+
+ return line;
+}