talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 1be05377aec177b2503b51e186a9c7ceadc7d8da
parent 5fe6b16b533e148a4e36ac51eaa972bbcd48496f
Author: Andrej Kacian <ticho@claws-mail.org>
Date:   Fri,  1 Mar 2019 15:45:45 +0100

Rewrite pgp_locate_armor_header() to more strictly follow RFC4880

Not only has the armor header be at the beginning of
the line, but also there cannot be any non-whitespace
after it on the same line.

Diffstat:
Mconfigure.ac | 1+
Msrc/plugins/pgpcore/Makefile.am | 8+++++---
Msrc/plugins/pgpcore/pgp_utils.c | 64+++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/plugins/pgpcore/pgp_utils.h | 2+-
Asrc/plugins/pgpcore/tests/Makefile.am | 18++++++++++++++++++
Asrc/plugins/pgpcore/tests/pgp_utils_test.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 159 insertions(+), 19 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -2147,6 +2147,7 @@ src/plugins/perl/tools/Makefile src/plugins/python/Makefile src/plugins/python/examples/Makefile src/plugins/pgpcore/Makefile +src/plugins/pgpcore/tests/Makefile src/plugins/pgpmime/Makefile src/plugins/pgpinline/Makefile src/plugins/rssyl/Makefile diff --git a/src/plugins/pgpcore/Makefile.am b/src/plugins/pgpcore/Makefile.am @@ -3,6 +3,11 @@ # terms of the General Public License version 3 (or later). # See COPYING file for license details. +if BUILD_TESTS +include $(top_srcdir)/tests.mk +SUBDIRS = . tests +endif + EXTRA_DIST = version.rc plugin.def claws.def IFLAGS = \ @@ -94,6 +99,3 @@ pgpcore_la_CPPFLAGS = \ clean-local: rm -f libclaws.a - - -.PHONY: test diff --git a/src/plugins/pgpcore/pgp_utils.c b/src/plugins/pgpcore/pgp_utils.c @@ -27,23 +27,57 @@ #include <glib.h> -#include "pgp_utils.h" -#include "codeconv.h" -#include "file-utils.h" - -gchar *pgp_locate_armor_header(gchar *textdata, const gchar *armor_header) +/* It's only a valid armor header if it's at the + * beginning of the buffer or a new line, and if + * there is only whitespace after it on the rest + * of the line. */ +gchar *pgp_locate_armor_header(const gchar *haystack, const gchar *needle) { - gchar *pos; - - pos = strstr(textdata, armor_header); - /* - * It's only a valid armor header if it's at the - * beginning of the buffer or a new line. - */ - if (pos != NULL && (pos == textdata || *(pos-1) == '\n')) - { - return pos; + gchar *txt, *x, *i; + gint ok; + + g_return_val_if_fail(haystack != NULL, NULL); + g_return_val_if_fail(needle != NULL, NULL); + + /* Start at the beginning */ + txt = (gchar *)haystack; + while (*txt != '\0') { + + /* Find next occurrence */ + x = strstr(txt, needle); + + if (x == NULL) + break; + + /* Make sure that what we found is at the beginning of line */ + if (x != haystack && *(x - 1) != '\n') { + txt = x + 1; + continue; + } + + /* Now look at what's between end of needle and end of that line. + * If there is anything else than whitespace, stop looking. */ + i = x + strlen(needle); + ok = 1; + while (*i != '\0' && *i != '\r' && *i != '\n') { + if (!g_ascii_isspace(*i)) { + ok = 0; + break; + } + i++; + } + + if (ok) + return x; + + /* We are at the end of haystack */ + if (*i == '\0') + return NULL; + + txt = i + 1; } + return NULL; } + #endif /* USE_GPGME */ diff --git a/src/plugins/pgpcore/pgp_utils.h b/src/plugins/pgpcore/pgp_utils.h @@ -27,6 +27,6 @@ #include "procmime.h" -gchar *pgp_locate_armor_header(gchar *textdata, const gchar *armor_header); +gchar *pgp_locate_armor_header(const gchar *textdata, const gchar *armor_header); #endif /* __PGP_UTILS_H__ */ diff --git a/src/plugins/pgpcore/tests/Makefile.am b/src/plugins/pgpcore/tests/Makefile.am @@ -0,0 +1,18 @@ +include $(top_srcdir)/tests.mk + +common_ldadd = \ + $(GLIB_LIBS) + +AM_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + -I.. \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/common + +TEST_PROGS += pgp_utils_test +pgp_utils_test_SOURCES = pgp_utils_test.c +pgp_utils_test_LDADD = $(common_ldadd) ../pgpcore_la-pgp_utils.o + +noinst_PROGRAMS = $(TEST_PROGS) + +.PHONY: test diff --git a/src/plugins/pgpcore/tests/pgp_utils_test.c b/src/plugins/pgpcore/tests/pgp_utils_test.c @@ -0,0 +1,85 @@ +#include "pgp_utils.h" + +#define HEADER "HEADER" +struct td { + gchar *input; + gchar *expected_output; +}; + +static void +test_pgp_locate_armor_header_null() +{ + if (!g_test_undefined()) + return; + + if (g_test_subprocess()) { + gchar *out = pgp_locate_armor_header(NULL, HEADER); + g_assert_null(out); + return; + } + + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_stderr("*assertion*failed*"); + g_test_trap_assert_failed(); +} + +static void +test_pgp_locate_armor_header(gconstpointer user_data) +{ + struct td *data = (struct td *)user_data; + gchar *out = pgp_locate_armor_header(data->input, HEADER); + + g_assert_cmpstr(out, ==, data->expected_output); +} + +struct td td_justheader = { + "HEADER", + "HEADER" +}; + +struct td td_leading = { + "leadingHEADER", + NULL +}; + +struct td td_trailingspaces = { + "HEADER ", + "HEADER " +}; + +struct td td_trailingtext1 = { + "HEADERblah", + NULL +}; + +struct td td_trailingtext2 = { + "HEADER blah", + NULL +}; + +struct td td_leadinglines = { + "foo\nHEADER\nbar", + "HEADER\nbar" +}; + +#define TEST(name, data) \ + g_test_add_data_func("/plugins/pgpcore/pgp_locate_armor_header_"name, \ + &data, \ + test_pgp_locate_armor_header) +int +main (int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/plugins/pgpcore/pgp_locate_armor_header_null", + test_pgp_locate_armor_header_null); + + TEST("justheader", td_justheader); + TEST("leading", td_leading); + TEST("trailingspaces", td_trailingspaces); + TEST("trailingtext1", td_trailingtext1); + TEST("trailingtext2", td_trailingtext2); + TEST("leadinglines", td_leadinglines); + + return g_test_run(); +}