diff --git a/usr.bin/hexdump/conv.c b/usr.bin/hexdump/conv.c index 95a1becb2dc0..f137e1076e63 100644 --- a/usr.bin/hexdump/conv.c +++ b/usr.bin/hexdump/conv.c @@ -56,6 +56,7 @@ conv_c(PR *pr, u_char *p, size_t bufsize) size_t clen, oclen; int converr, pad, width; u_char peekbuf[MB_LEN_MAX]; + u_char *op; if (pr->mbleft > 0) { str = "**"; @@ -107,6 +108,15 @@ conv_c(PR *pr, u_char *p, size_t bufsize) else if (clen == (size_t)-1 || (clen == (size_t)-2 && p == peekbuf)) { memset(&pr->mbstate, 0, sizeof(pr->mbstate)); + if (p == peekbuf) { + /* + * We peeked ahead, but that didn't help -- + * we either got an illegal sequence or still + * can't complete; restore original character. + */ + oclen = 0; + p = op; + } wc = *p; clen = 1; converr = 1; @@ -116,6 +126,7 @@ conv_c(PR *pr, u_char *p, size_t bufsize) * can complete it. */ oclen = bufsize; + op = p; bufsize = peek(p = peekbuf, MB_CUR_MAX); goto retry; } @@ -128,7 +139,7 @@ conv_c(PR *pr, u_char *p, size_t bufsize) if (!odmode) { *pr->cchar = 'c'; (void)printf(pr->fmt, (int)wc); - } else { + } else { *pr->cchar = 'C'; assert(strcmp(pr->fmt, "%3C") == 0); width = wcwidth(wc); diff --git a/usr.bin/hexdump/tests/Makefile b/usr.bin/hexdump/tests/Makefile index 192e10670025..4c81860d6dc2 100644 --- a/usr.bin/hexdump/tests/Makefile +++ b/usr.bin/hexdump/tests/Makefile @@ -2,7 +2,7 @@ PACKAGE= tests -ATF_TESTS_SH= hexdump_test +ATF_TESTS_SH= hexdump_test od_test ${PACKAGE}FILES+= d_hexdump_a.in ${PACKAGE}FILES+= d_hexdump_b.in @@ -27,5 +27,7 @@ ${PACKAGE}FILES+= d_hexdump_UCflag_c.out ${PACKAGE}FILES+= d_hexdump_xflag_a.out ${PACKAGE}FILES+= d_hexdump_xflag_b.out ${PACKAGE}FILES+= d_hexdump_xflag_c.out +${PACKAGE}FILES+= d_od_cflag_a.out +${PACKAGE}FILES+= d_od_cflag_b.out .include diff --git a/usr.bin/hexdump/tests/d_od_cflag_a.out b/usr.bin/hexdump/tests/d_od_cflag_a.out new file mode 100644 index 000000000000..db8037f0824d --- /dev/null +++ b/usr.bin/hexdump/tests/d_od_cflag_a.out @@ -0,0 +1,3 @@ +0000000 T e s t T e s t T e s t T e s 345 +0000020 T e s t 345 +0000025 diff --git a/usr.bin/hexdump/tests/d_od_cflag_b.out b/usr.bin/hexdump/tests/d_od_cflag_b.out new file mode 100644 index 000000000000..bd9e9d1dddfb --- /dev/null +++ b/usr.bin/hexdump/tests/d_od_cflag_b.out @@ -0,0 +1,3 @@ +0000000 T e s t T e s t T e s t T e s т +0000020 ** Т ** е ** с ** т ** +0000031 diff --git a/usr.bin/hexdump/tests/od_test.sh b/usr.bin/hexdump/tests/od_test.sh new file mode 100755 index 000000000000..722873b34125 --- /dev/null +++ b/usr.bin/hexdump/tests/od_test.sh @@ -0,0 +1,94 @@ +# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# +# Copyright 2018 (C) Yuri Pankov +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ + +atf_test_case c_flag +c_flag_head() +{ + atf_set "descr" "Verify -c output (PR 224552)" +} +c_flag_body() +{ + export LC_ALL="en_US.UTF-8" + + printf 'TestTestTestTes\345Test\345' > d_od_cflag.in + atf_check -o file:"$(atf_get_srcdir)/d_od_cflag_a.out" \ + od -c d_od_cflag.in + printf 'TestTestTestTesтТест' > d_od_cflag.in + atf_check -o file:"$(atf_get_srcdir)/d_od_cflag_b.out" \ + od -c d_od_cflag.in +} + +atf_init_test_cases() +{ + atf_add_test_case c_flag +} +# +# Copyright 2018 The FreeBSD Project +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ + +atf_test_case c_flag +c_flag_head() +{ + atf_set "descr" "Verify -c output" +} +c_flag_body() +{ + printf 'TestTestTestTes\345Test\345' > d_od_cflag.in + atf_check -o file:"$(atf_get_srcdir)/d_od_cflag_a.out" \ + env LC_CTYPE="en_US.UTF-8" od -c "d_od_cflag.in" + printf 'TestTestTestTesтТест' > d_od_cflag.in + atf_check -o file:"$(atf_get_srcdir)/d_od_cflag_b.out" \ + env LC_CTYPE="en_US.UTF-8" od -c "d_od_cflag.in" +} + +atf_init_test_cases() +{ + atf_add_test_case c_flag +}