ICU-21069 Fix ucptrie_swap pointer logic
See #1102
diff --git a/icu4c/source/common/utrie_swap.cpp b/icu4c/source/common/utrie_swap.cpp
index 5abe7bd..6e8b138 100644
--- a/icu4c/source/common/utrie_swap.cpp
+++ b/icu4c/source/common/utrie_swap.cpp
@@ -256,20 +256,24 @@ ucptrie_swap(const UDataSwapper *ds,
ds->swapArray32(ds, &inTrie->signature, 4, &outTrie->signature, pErrorCode);
ds->swapArray16(ds, &inTrie->options, 12, &outTrie->options, pErrorCode);
- /* swap the index and the data */
+ /* swap the index */
+ const uint16_t *inIndex=reinterpret_cast<const uint16_t *>(inTrie+1);
+ uint16_t *outIndex=reinterpret_cast<uint16_t *>(outTrie+1);
+ ds->swapArray16(ds, inIndex, trie.indexLength*2, outIndex, pErrorCode);
+
+ /* swap the data */
+ const uint16_t *inData=inIndex+trie.indexLength;
+ uint16_t *outData=outIndex+trie.indexLength;
switch(valueWidth) {
case UCPTRIE_VALUE_BITS_16:
- ds->swapArray16(ds, inTrie+1, (trie.indexLength+dataLength)*2, outTrie+1, pErrorCode);
+ ds->swapArray16(ds, inData, dataLength*2, outData, pErrorCode);
break;
case UCPTRIE_VALUE_BITS_32:
- ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode);
- ds->swapArray32(ds, (const uint16_t *)(inTrie+1)+trie.indexLength, dataLength*4,
- (uint16_t *)(outTrie+1)+trie.indexLength, pErrorCode);
+ ds->swapArray32(ds, inData, dataLength*4, outData, pErrorCode);
break;
case UCPTRIE_VALUE_BITS_8:
- ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode);
if(inTrie!=outTrie) {
- uprv_memmove((outTrie+1)+trie.indexLength, (inTrie+1)+trie.indexLength, dataLength);
+ uprv_memmove(outData, inData, dataLength);
}
break;
default:
diff --git a/icu4c/source/test/cintltst/ucptrietest.c b/icu4c/source/test/cintltst/ucptrietest.c
index 9d2e489..cbeb43d 100644
--- a/icu4c/source/test/cintltst/ucptrietest.c
+++ b/icu4c/source/test/cintltst/ucptrietest.c
@@ -1145,6 +1145,9 @@ TrieTestSet3Initial9(void) {
testTrieRanges("set3-initial-9", FALSE,
setRanges3, UPRV_LENGTHOF(setRanges3),
checkRanges3, UPRV_LENGTHOF(checkRanges3));
+ testTrieRanges("set3-initial-9-clone", TRUE,
+ setRanges3, UPRV_LENGTHOF(setRanges3),
+ checkRanges3, UPRV_LENGTHOF(checkRanges3));
}
static void