From 5d36a4ff4e89367e9aee5517f60322c79c4c3c0d Mon Sep 17 00:00:00 2001 From: Brian Pane Date: Mon, 21 Jul 2014 11:26:19 -0700 Subject: [PATCH] Fix the unaligned string toLowerAscii test Summary: * The test computed nonaligned inputs but then copied them into temporary buffers to compare different implementations. The temporary buffers were word-aligned. * This diff keeps the temp buffers but ensures that the data in them keeps the original input's alignment. Test Plan: * Ran the test case with a modified String.cpp containing an assert to catch unaligned reads. The assert failed, as expected, on a copy of the code without the fix from D1434585 Reviewed By: meyering@fb.com Subscribers: ruibalp FB internal diff: D1435028 Tasks: 4696800 --- folly/test/StringTest.cpp | 40 +++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/folly/test/StringTest.cpp b/folly/test/StringTest.cpp index b283161a..f2162567 100644 --- a/folly/test/StringTest.cpp +++ b/folly/test/StringTest.cpp @@ -1079,11 +1079,37 @@ TEST(String, humanify) { namespace { +/** + * Copy bytes from src to somewhere in the buffer referenced by dst. The + * actual starting position of the copy will be the first address in the + * destination buffer whose address mod 8 is equal to the src address mod 8. + * The caller is responsible for ensuring that the destination buffer has + * enough extra space to accommodate the shifted copy. + */ +char* copyWithSameAlignment(char* dst, const char* src, size_t length) { + const char* originalDst = dst; + size_t dstOffset = size_t(dst) & 0x7; + size_t srcOffset = size_t(src) & 0x7; + while (dstOffset != srcOffset) { + dst++; + dstOffset++; + dstOffset &= 0x7; + } + CHECK(dst <= originalDst + 7); + CHECK((size_t(dst) & 0x7) == (size_t(src) & 0x7)); + memcpy(dst, src, length); + return dst; +} + void testToLowerAscii(Range src) { - char control[src.size()]; - memcpy(control, src.begin(), src.size()); - char test[src.size()]; - memcpy(test, src.begin(), src.size()); + // Allocate extra space so we can make copies that start at the + // same alignment (byte, word, quadword, etc) as the source buffer. + char controlBuf[src.size() + 7]; + char* control = copyWithSameAlignment(controlBuf, src.begin(), src.size()); + + char testBuf[src.size() + 7]; + char* test = copyWithSameAlignment(testBuf, src.begin(), src.size()); + for (size_t i = 0; i < src.size(); i++) { control[i] = tolower(control[i]); } @@ -1112,8 +1138,10 @@ TEST(String, toLowerAsciiUnaligned) { } // Test input buffers of several lengths to exercise all the // cases: buffer at the start/middle/end of an aligned block, plus - // buffers that span multiple aligned blocks. - for (size_t length = 1; length < 11; length++) { + // buffers that span multiple aligned blocks. The longest test input + // is 3 unaligned bytes + 4 32-bit aligned bytes + 8 64-bit aligned + // + 4 32-bit aligned + 3 unaligned = 22 bytes. + for (size_t length = 1; length < 23; length++) { for (size_t offset = 0; offset + length <= kSize; offset++) { testToLowerAscii(Range(input + offset, length)); } -- 2.34.1