From b7e1a1d30fd5478456f2a19f0fbb7bc1e6388109 Mon Sep 17 00:00:00 2001 From: Ken Hornstein Date: Thu, 2 Jan 2014 14:46:52 -0500 Subject: [PATCH] Fix problem with %(putlit) and %(zputlit) causing a SIGSEGV if str is NULL. --- Makefile.am | 1 + docs/pending-release-notes | 2 ++ sbr/fmt_scan.c | 40 ++++++++++++++++++++------------------ test/format/test-nullstr | 31 +++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 19 deletions(-) create mode 100755 test/format/test-nullstr diff --git a/Makefile.am b/Makefile.am index 92743f43..2a3af9bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,6 +54,7 @@ TESTS = test/ali/test-ali test/anno/test-anno \ test/format/test-dp test/format/test-fmtdump \ test/format/test-localmbox test/format/test-myname \ test/format/test-myhost test/format/test-mymbox \ + test/format/test-nullstr \ test/format/test-rightjustify \ test/format/test-unquote \ test/forw/test-forw-digest test/forw/test-forw-format \ diff --git a/docs/pending-release-notes b/docs/pending-release-notes index d5a9a27d..1242e543 100644 --- a/docs/pending-release-notes +++ b/docs/pending-release-notes @@ -145,3 +145,5 @@ BUG FIXES $HOME/.netrc. - Added quoting of local part of invalid address in message being replied to [Bug #26780]. +- Fix segmentation fauls for %(putlit) and %(zputlit) format escapes when + the "str" register was NULL. diff --git a/sbr/fmt_scan.c b/sbr/fmt_scan.c index ab5940ab..4460c628 100644 --- a/sbr/fmt_scan.c +++ b/sbr/fmt_scan.c @@ -467,29 +467,31 @@ fmt_scan (struct format *format, char *scanl, size_t max, int width, int *dat, scanl + max - 1); break; case FT_STRLIT: - sp = str; - while ((c = *sp++) && cp < ep) - *cp++ = c; + if (str) { + sp = str; + while ((c = *sp++) && cp < ep) + *cp++ = c; + } break; - case FT_STRLITZ: { - size_t len = strlen (str); - - /* Don't want to emit part of an escape sequence. So if - there isn't enough room in the buffer for the entire - string, skip it completely. */ - if (cp - scanl + len + 1 < max) { - for (sp = str; *sp; *cp++ = *sp++) continue; - - /* This string doesn't count against the width. So - increase ep the same amount as cp, only if the - scan buffer will always be large enough. */ - if (ep - scanl + len + 1 < max) { - ep += len; + case FT_STRLITZ: + if (str) { + size_t len = strlen (str); + + /* Don't want to emit part of an escape sequence. So if + there isn't enough room in the buffer for the entire + string, skip it completely. */ + if (cp - scanl + len + 1 < max) { + for (sp = str; *sp; *cp++ = *sp++) continue; + + /* This string doesn't count against the width. + So increase ep the same amount as cp, only if the + scan buffer will always be large enough. */ + if (ep - scanl + len + 1 < max) { + ep += len; + } } } - break; - } case FT_STRFW: adios (NULL, "internal error (FT_STRFW)"); diff --git a/test/format/test-nullstr b/test/format/test-nullstr new file mode 100755 index 00000000..644c0bc0 --- /dev/null +++ b/test/format/test-nullstr @@ -0,0 +1,31 @@ +#!/bin/sh +# +# Test that a NULL str register doesn't cause the string handling format +# escapes to fail. +# + +set -e + +if test -z "${MH_OBJ_DIR}"; then + srcdir=`dirname "$0"`/../.. + MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR +fi + +. "$MH_OBJ_DIR/test/common.sh" + +setup_test + +# +# %{null} is arbitrary; it could be any component that does not exist. +# + +run_test "fmttest -raw -format Test%(putstr{null}) dummy" "Test" \ + "Test of %(putstr)" +run_test "fmttest -raw -format Test%10(putstrf{null}) dummy" "Test " \ + "Test of %(putstrf)" +run_test "fmttest -raw -format Test%(putlit{null}) dummy" "Test" \ + "Test of %(putlit)" +run_test "fmttest -raw -format Test%(zputlit{null}) dummy" "Test" \ + "Test of %(zputlit)" + +exit $failed -- 2.56.0