From patchwork Mon Sep 9 15:58:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Schwab X-Patchwork-Id: 34455 Received: (qmail 28377 invoked by alias); 9 Sep 2019 15:58:18 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 28324 invoked by uid 89); 9 Sep 2019 15:58:17 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-15.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_PASS autolearn=ham version=3.3.1 spammy=areas X-HELO: mx1.suse.de From: Andreas Schwab To: libc-alpha@sourceware.org Subject: [PATCH] Fix buffer overrun in EUC-KR conversion module (bug 24973) X-Yow: America!! I saw it all!! Vomiting! Waving! JERRY FALWELLING into your void tube of UHF oblivion!! SAFEWAY of the mind -- Date: Mon, 09 Sep 2019 17:58:12 +0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 The byte 0xfe as input to the EUC-KR conversion denotes a user-defined area and is not allowed. The from_euc_kr function used to skip two bytes when told to skip over the invalid byte, potentially running over the buffer end. [BZ #24973] * iconvdata/euc-kr.c (BODY for FROM_LOOP): Skip only one byte when encountering 0xfe. * iconv/Makefile (tests): Add tst-iconv8. * iconv/tst-iconv8.c: New file. --- iconv/Makefile | 2 +- iconv/tst-iconv8.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ iconvdata/euc-kr.c | 2 +- 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 iconv/tst-iconv8.c diff --git a/iconv/Makefile b/iconv/Makefile index b7a8f5e0d4..62bbd4e872 100644 --- a/iconv/Makefile +++ b/iconv/Makefile @@ -44,7 +44,7 @@ CFLAGS-linereader.c += -DNO_TRANSLITERATION CFLAGS-simple-hash.c += -I../locale tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \ - tst-iconv7 tst-iconv-mt + tst-iconv7 tst-iconv8 tst-iconv-mt others = iconv_prog iconvconfig install-others-programs = $(inst_bindir)/iconv diff --git a/iconv/tst-iconv8.c b/iconv/tst-iconv8.c new file mode 100644 index 0000000000..64bf863cd7 --- /dev/null +++ b/iconv/tst-iconv8.c @@ -0,0 +1,49 @@ +/* Test EUC-KR module + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Derived from BZ #24973 */ +#include +#include +#include +#include + +static int +do_test (void) +{ + iconv_t cd = iconv_open ("UTF-8//IGNORE", "EUC-KR"); + TEST_VERIFY_EXIT (cd != (iconv_t) -1); + + /* 0xfe (->0x7e : row 94) is a user-defined area. It is not allowed and + should be skipped over due to //IGNORE. */ + char input[2] = { '\0', '\xfe' }; + char *inptr = input; + size_t insize = sizeof (input); + char output[4]; + char *outptr = output; + size_t outsize = sizeof (output); + + /* This used to crash due to buffer overrun. */ + TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == (size_t) -1); + TEST_VERIFY (errno == EILSEQ); + + TEST_VERIFY_EXIT (iconv_close (cd) != -1); + + return 0; +} + +#include diff --git a/iconvdata/euc-kr.c b/iconvdata/euc-kr.c index 379414c426..167a554719 100644 --- a/iconvdata/euc-kr.c +++ b/iconvdata/euc-kr.c @@ -83,7 +83,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp) /* 0xfe(->0x7e : row 94) and 0xc9(->0x59 : row 41) are \ user-defined areas. */ \ else if (__builtin_expect (ch == 0xa0, 0) \ - || __builtin_expect (ch > 0xfe, 0) \ + || __builtin_expect (ch >= 0xfe, 0) \ || __builtin_expect (ch == 0xc9, 0)) \ { \ /* This is illegal. */ \