From 90b7a6e4e80ffa6cfd047c20e65dd9653462012d Mon Sep 17 00:00:00 2001 From: Markus Scherer Date: Fri, 8 Dec 2017 21:47:21 +0000 Subject: [PATCH] ICU-13510 test & fix UTF-8->UTF-8 conversion overflow for supplementary characters X-SVN-Rev: 40715 --- icu4c/source/common/ucnv_u8.cpp | 10 ++++++- icu4c/source/test/intltest/convtest.cpp | 35 ++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/icu4c/source/common/ucnv_u8.cpp b/icu4c/source/common/ucnv_u8.cpp index e47b86c5b93..5d72f8ef377 100644 --- a/icu4c/source/common/ucnv_u8.cpp +++ b/icu4c/source/common/ucnv_u8.cpp @@ -814,7 +814,7 @@ moreBytes: } /* copy the legal byte sequence to the target */ - { + if(count>=toULength) { int8_t i; for(i=0; isource=(char *)source; + pFromUArgs->target=(char *)target; + *pErrorCode=U_USING_DEFAULT_WARNING; + return; } } } diff --git a/icu4c/source/test/intltest/convtest.cpp b/icu4c/source/test/intltest/convtest.cpp index fc03ff6adc6..db0aa86912b 100644 --- a/icu4c/source/test/intltest/convtest.cpp +++ b/icu4c/source/test/intltest/convtest.cpp @@ -723,7 +723,7 @@ ConversionTest::TestUTF8ToUTF8Overflow() { IcuTestErrorCode errorCode(*this, "TestUTF8ToUTF8Overflow"); LocalUConverterPointer cnv1(ucnv_open("UTF-8", errorCode)); LocalUConverterPointer cnv2(ucnv_open("UTF-8", errorCode)); - static const char *text = "aä"; + static const char *text = "aä"; // ä: 2 bytes const char *source = text; const char *sourceLimit = text + strlen(text); char result[20]; @@ -757,6 +757,39 @@ ConversionTest::TestUTF8ToUTF8Overflow() { if (length == 3) { assertTrue("result same as input", memcmp(text, result, length) == 0); } + + ucnv_reset(cnv1.getAlias()); + ucnv_reset(cnv2.getAlias()); + memset(result, 0, sizeof(result)); + static const char *text2 = "a🚲"; // U+1F6B2 bicycle: 4 bytes + source = text2; + sourceLimit = text2 + strlen(text2); + target = result; + pivotSource = pivotTarget = buffer16; + + // Convert with insufficient target capacity. + result[3] = 5; + ucnv_convertEx(cnv2.getAlias(), cnv1.getAlias(), + &target, result + 3, &source, sourceLimit, + buffer16, &pivotSource, &pivotTarget, pivotLimit, + FALSE, FALSE, errorCode); + assertEquals("text2 overflow", U_BUFFER_OVERFLOW_ERROR, errorCode.reset()); + length = (int32_t)(target - result); + assertEquals("text2 number of bytes written", 3, length); + assertEquals("text2 next byte not clobbered", 5, result[3]); + + // Convert the rest and flush. + ucnv_convertEx(cnv2.getAlias(), cnv1.getAlias(), + &target, targetLimit, &source, sourceLimit, + buffer16, &pivotSource, &pivotTarget, pivotLimit, + FALSE, TRUE, errorCode); + + assertSuccess("text2 UTF-8->UTF-8", errorCode); + length = (int32_t)(target - result); + assertEquals("text2 5 bytes", 5, length); + if (length == 5) { + assertTrue("text2 result same as input", memcmp(text2, result, length) == 0); + } } // open testdata or ICU data converter ------------------------------------- *** -- 2.50.1