Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdlib.h>
     18 #include <string.h>
     19 #include <sys/mman.h>
     20 
     21 #include <gtest/gtest.h>
     22 #include "buffer_tests.h"
     23 
     24 // For the comparison buffer tests, the maximum length to test for the
     25 // miscompare checks.
     26 #define MISCMP_MAX_LENGTH 512
     27 
     28 #define FENCEPOST_LENGTH 8
     29 
     30 static int g_single_aligns[][2] = {
     31   // Both buffers at same alignment.
     32   { 1, 0 },
     33   { 2, 0 },
     34   { 4, 0 },
     35   { 8, 0 },
     36   { 16, 0 },
     37   { 32, 0 },
     38   { 64, 0 },
     39   { 128, 0 },
     40 
     41   // General unaligned cases.
     42   { 4, 1 },
     43   { 4, 2 },
     44   { 4, 3 },
     45 
     46   { 8, 1 },
     47   { 8, 2 },
     48   { 8, 3 },
     49   { 8, 4 },
     50   { 8, 5 },
     51   { 8, 6 },
     52   { 8, 7 },
     53 
     54   { 128, 1 },
     55   { 128, 4 },
     56   { 128, 8 },
     57   { 128, 12 },
     58   { 128, 16 },
     59 };
     60 
     61 static const size_t g_single_aligns_len = sizeof(g_single_aligns)/sizeof(int[2]);
     62 
     63 // Set of multiple buffer alignment combinations to be used for string/memory
     64 // testing routines.
     65 static int g_double_aligns[][4] = {
     66   // Both buffers at same alignment.
     67   { 1, 0, 1, 0 },
     68   { 2, 0, 2, 0 },
     69   { 4, 0, 4, 0 },
     70   { 8, 0, 8, 0 },
     71   { 16, 0, 16, 0 },
     72   { 32, 0, 32, 0 },
     73   { 64, 0, 64, 0 },
     74   { 128, 0, 128, 0 },
     75 
     76   // Different word alignments between buffers.
     77   { 8, 0, 4, 0 },
     78   { 4, 0, 8, 0 },
     79   { 16, 0, 4, 0 },
     80   { 4, 0, 16, 0 },
     81 
     82   // General unaligned cases.
     83   { 4, 0, 4, 1 },
     84   { 4, 0, 4, 2 },
     85   { 4, 0, 4, 3 },
     86 
     87   { 4, 1, 4, 0 },
     88   { 4, 1, 4, 1 },
     89   { 4, 1, 4, 2 },
     90   { 4, 1, 4, 3 },
     91 
     92   { 4, 2, 4, 0 },
     93   { 4, 2, 4, 1 },
     94   { 4, 2, 4, 2 },
     95   { 4, 2, 4, 3 },
     96 
     97   { 4, 3, 4, 0 },
     98   { 4, 3, 4, 1 },
     99   { 4, 3, 4, 2 },
    100   { 4, 3, 4, 3 },
    101 
    102   { 8, 0, 8, 1 },
    103   { 8, 0, 8, 2 },
    104   { 8, 0, 8, 3 },
    105   { 8, 0, 8, 4 },
    106   { 8, 0, 8, 5 },
    107   { 8, 0, 8, 6 },
    108   { 8, 0, 8, 7 },
    109 
    110   { 8, 1, 8, 0 },
    111   { 8, 1, 8, 1 },
    112   { 8, 1, 8, 2 },
    113   { 8, 1, 8, 3 },
    114   { 8, 1, 8, 4 },
    115   { 8, 1, 8, 5 },
    116   { 8, 1, 8, 6 },
    117   { 8, 1, 8, 7 },
    118 
    119   { 8, 2, 8, 0 },
    120   { 8, 2, 8, 1 },
    121   { 8, 2, 8, 2 },
    122   { 8, 2, 8, 3 },
    123   { 8, 2, 8, 4 },
    124   { 8, 2, 8, 5 },
    125   { 8, 2, 8, 6 },
    126   { 8, 2, 8, 7 },
    127 
    128   { 8, 3, 8, 0 },
    129   { 8, 3, 8, 1 },
    130   { 8, 3, 8, 2 },
    131   { 8, 3, 8, 3 },
    132   { 8, 3, 8, 4 },
    133   { 8, 3, 8, 5 },
    134   { 8, 3, 8, 6 },
    135   { 8, 3, 8, 7 },
    136 
    137   { 8, 4, 8, 0 },
    138   { 8, 4, 8, 1 },
    139   { 8, 4, 8, 2 },
    140   { 8, 4, 8, 3 },
    141   { 8, 4, 8, 4 },
    142   { 8, 4, 8, 5 },
    143   { 8, 4, 8, 6 },
    144   { 8, 4, 8, 7 },
    145 
    146   { 8, 5, 8, 0 },
    147   { 8, 5, 8, 1 },
    148   { 8, 5, 8, 2 },
    149   { 8, 5, 8, 3 },
    150   { 8, 5, 8, 4 },
    151   { 8, 5, 8, 5 },
    152   { 8, 5, 8, 6 },
    153   { 8, 5, 8, 7 },
    154 
    155   { 8, 6, 8, 0 },
    156   { 8, 6, 8, 1 },
    157   { 8, 6, 8, 2 },
    158   { 8, 6, 8, 3 },
    159   { 8, 6, 8, 4 },
    160   { 8, 6, 8, 5 },
    161   { 8, 6, 8, 6 },
    162   { 8, 6, 8, 7 },
    163 
    164   { 8, 7, 8, 0 },
    165   { 8, 7, 8, 1 },
    166   { 8, 7, 8, 2 },
    167   { 8, 7, 8, 3 },
    168   { 8, 7, 8, 4 },
    169   { 8, 7, 8, 5 },
    170   { 8, 7, 8, 6 },
    171   { 8, 7, 8, 7 },
    172 
    173   { 128, 1, 128, 4 },
    174   { 128, 1, 128, 8 },
    175   { 128, 1, 128, 12 },
    176   { 128, 1, 128, 16 },
    177   { 128, 4, 128, 1 },
    178   { 128, 8, 128, 1 },
    179   { 128, 12, 128, 1 },
    180   { 128, 16, 128, 1 },
    181 };
    182 
    183 static const size_t g_double_aligns_len = sizeof(g_double_aligns)/sizeof(int[4]);
    184 
    185 static size_t SetIncrement(size_t len) {
    186   if (len >= 4096) {
    187     return 1024;
    188   } else if (len >= 1024) {
    189     return 256;
    190   }
    191   return 1;
    192 }
    193 
    194 // Return a pointer into the current buffer with the specified alignment.
    195 static void *GetAlignedPtr(void *orig_ptr, int alignment, int or_mask) {
    196   uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr);
    197   if (alignment > 0) {
    198       // When setting the alignment, set it to exactly the alignment chosen.
    199       // The pointer returned will be guaranteed not to be aligned to anything
    200       // more than that.
    201       ptr += alignment - (ptr & (alignment - 1));
    202       ptr |= alignment | or_mask;
    203   }
    204 
    205   return reinterpret_cast<void*>(ptr);
    206 }
    207 
    208 static void SetFencepost(uint8_t *buffer) {
    209   for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
    210     buffer[i] = 0xde;
    211     buffer[i+1] = 0xad;
    212   }
    213 }
    214 
    215 static void VerifyFencepost(uint8_t *buffer) {
    216   for (int i = 0; i < FENCEPOST_LENGTH; i += 2) {
    217     if (buffer[i] != 0xde || buffer[i+1] != 0xad) {
    218       uint8_t expected_value;
    219       if (buffer[i] == 0xde) {
    220         i++;
    221         expected_value = 0xad;
    222       } else {
    223         expected_value = 0xde;
    224       }
    225       ASSERT_EQ(expected_value, buffer[i]);
    226     }
    227   }
    228 }
    229 
    230 void RunSingleBufferAlignTest(
    231     size_t max_test_size, void (*test_func)(uint8_t*, size_t),
    232     size_t (*set_incr)(size_t)) {
    233   if (!set_incr) {
    234     set_incr = SetIncrement;
    235   }
    236 
    237   // Allocate one large buffer with lots of extra space so that we can
    238   // guarantee that the all possible alignments will fit.
    239   uint8_t *buf = new uint8_t[3*max_test_size];
    240 
    241   uint8_t *buf_align;
    242   for (size_t i = 0; i < g_single_aligns_len; i++) {
    243     size_t incr = 1;
    244     for (size_t len = 0; len <= max_test_size; len += incr) {
    245       incr = set_incr(len);
    246 
    247       buf_align = reinterpret_cast<uint8_t*>(GetAlignedPtr(
    248           buf+FENCEPOST_LENGTH, g_single_aligns[i][0], g_single_aligns[i][1]));
    249 
    250       SetFencepost(&buf_align[-FENCEPOST_LENGTH]);
    251       SetFencepost(&buf_align[len]);
    252 
    253       test_func(buf_align, len);
    254 
    255       VerifyFencepost(&buf_align[-FENCEPOST_LENGTH]);
    256       VerifyFencepost(&buf_align[len]);
    257     }
    258   }
    259   delete[] buf;
    260 }
    261 
    262 void RunSrcDstBufferAlignTest(
    263     size_t max_test_size, void (*test_func)(uint8_t*, uint8_t*, size_t),
    264     size_t (*set_incr)(size_t)) {
    265   if (!set_incr) {
    266     set_incr = SetIncrement;
    267   }
    268 
    269   // Allocate two large buffers for all of the testing.
    270   uint8_t* src = new uint8_t[3*max_test_size];
    271   uint8_t* dst = new uint8_t[3*max_test_size];
    272 
    273   uint8_t* src_align;
    274   uint8_t* dst_align;
    275   for (size_t i = 0; i < g_double_aligns_len; i++) {
    276     size_t incr = 1;
    277     for (size_t len = 0; len <= max_test_size; len += incr) {
    278       incr = set_incr(len);
    279 
    280       src_align =
    281           reinterpret_cast<uint8_t*>(GetAlignedPtr(
    282               src+FENCEPOST_LENGTH, g_double_aligns[i][0], g_double_aligns[i][1]));
    283       dst_align =
    284           reinterpret_cast<uint8_t*>(GetAlignedPtr(
    285               dst+FENCEPOST_LENGTH, g_double_aligns[i][2], g_double_aligns[i][3]));
    286       SetFencepost(&dst_align[-FENCEPOST_LENGTH]);
    287       SetFencepost(&dst_align[len]);
    288 
    289       test_func(src_align, dst_align, len);
    290 
    291       VerifyFencepost(&dst_align[-FENCEPOST_LENGTH]);
    292       VerifyFencepost(&dst_align[len]);
    293     }
    294   }
    295   delete[] src;
    296   delete[] dst;
    297 }
    298 
    299 void RunCmpBufferAlignTest(
    300     size_t max_test_size, void (*test_cmp_func)(uint8_t*, uint8_t*, size_t),
    301     void (*test_miscmp_func)(uint8_t*, uint8_t*, size_t, size_t),
    302     size_t (*set_incr)(size_t)) {
    303   if (!set_incr) {
    304     set_incr = SetIncrement;
    305   }
    306 
    307   // Allocate two large buffers for all of the testing.
    308   uint8_t* buf1 = new uint8_t[3*max_test_size];
    309   uint8_t* buf2 = new uint8_t[3*max_test_size];
    310 
    311   uint8_t* buf1_align;
    312   uint8_t* buf2_align;
    313   for (size_t i = 0; i < g_double_aligns_len; i++) {
    314     size_t incr = 1;
    315     for (size_t len = 0; len <= max_test_size; len += incr) {
    316       incr = set_incr(len);
    317 
    318       buf1_align =
    319           reinterpret_cast<uint8_t*>(GetAlignedPtr(
    320               buf1, g_double_aligns[i][0], g_double_aligns[i][1]));
    321       buf2_align =
    322           reinterpret_cast<uint8_t*>(GetAlignedPtr(
    323               buf2, g_double_aligns[i][2], g_double_aligns[i][3]));
    324 
    325       // Check by putting all zeroes after both buffers.
    326       memset(buf1_align+len, 0, 32);
    327       memset(buf2_align+len, 0, 32);
    328       test_cmp_func(buf1_align, buf2_align, len);
    329 
    330       // Check by putting different values after both buffers.
    331       for (size_t j = 0; j < 32; j++) {
    332         buf1_align[len+j] = j;
    333         buf2_align[len+j] = j+1;
    334       }
    335       test_cmp_func(buf1_align, buf2_align, len);
    336 
    337       if (len > 0) {
    338         // Change the lengths of the buffers and verify that there are
    339         // miscompares.
    340         for (size_t len2 = len+1; len2 < len+32; len2++) {
    341           test_miscmp_func(buf1_align, buf2_align, len, len2);
    342           test_miscmp_func(buf1_align, buf2_align, len2, len);
    343         }
    344       }
    345     }
    346   }
    347   delete[] buf1;
    348   delete[] buf2;
    349 }
    350 
    351 void RunSingleBufferOverreadTest(void (*test_func)(uint8_t*, size_t)) {
    352   // In order to verify that functions are not reading past the end of the
    353   // src, create data that ends exactly at an unreadable memory boundary.
    354   size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
    355   uint8_t* memory;
    356   ASSERT_TRUE(posix_memalign(reinterpret_cast<void**>(&memory), pagesize,
    357                              2*pagesize) == 0);
    358   memset(memory, 0x23, 2*pagesize);
    359 
    360   // Make the second page unreadable and unwritable.
    361   ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_NONE) == 0);
    362 
    363   for (size_t i = 0; i < pagesize; i++) {
    364     uint8_t* buf = &memory[pagesize-i];
    365 
    366     test_func(buf, i);
    367   }
    368   ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
    369   free(memory);
    370 }
    371 
    372 void RunSrcDstBufferOverreadTest(void (*test_func)(uint8_t*, uint8_t*, size_t)) {
    373   // In order to verify that functions are not reading past the end of the
    374   // src, create data that ends exactly at an unreadable memory boundary.
    375   size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
    376   uint8_t* memory;
    377   ASSERT_TRUE(posix_memalign(reinterpret_cast<void**>(&memory), pagesize,
    378                              2*pagesize) == 0);
    379   memset(memory, 0x23, 2*pagesize);
    380 
    381   // Make the second page unreadable and unwritable.
    382   ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_NONE) == 0);
    383 
    384   uint8_t* dst_buffer = new uint8_t[2*pagesize];
    385   // Change the dst alignment as we change the source.
    386   for (size_t i = 0; i < 16; i++) {
    387     uint8_t* dst = &dst_buffer[i];
    388     for (size_t j = 0; j < pagesize; j++) {
    389       uint8_t* src = &memory[pagesize-j];
    390 
    391       test_func(src, dst, j);
    392     }
    393   }
    394   ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
    395   free(memory);
    396   delete[] dst_buffer;
    397 }
    398 
    399 void RunCmpBufferOverreadTest(
    400     void (*test_cmp_func)(uint8_t*, uint8_t*, size_t),
    401     void (*test_miscmp_func)(uint8_t*, uint8_t*, size_t, size_t)) {
    402   // In order to verify that functions are not reading past the end of either
    403   // of the bufs, create both buffers that end exactly at an unreadable memory
    404   // boundary.
    405   size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
    406   uint8_t* memory1;
    407   ASSERT_TRUE(posix_memalign(reinterpret_cast<void**>(&memory1), pagesize,
    408                              2*pagesize) == 0);
    409   memset(memory1, 0x23, 2*pagesize);
    410 
    411   // Make the second page unreadable and unwritable.
    412   ASSERT_TRUE(mprotect(&memory1[pagesize], pagesize, PROT_NONE) == 0);
    413 
    414   uint8_t* memory2;
    415   ASSERT_TRUE(posix_memalign(reinterpret_cast<void**>(&memory2), pagesize,
    416                              2*pagesize) == 0);
    417   memset(memory2, 0x23, 2*pagesize);
    418 
    419   // Make the second page unreadable and unwritable.
    420   ASSERT_TRUE(mprotect(&memory2[pagesize], pagesize, PROT_NONE) == 0);
    421 
    422   for (size_t i = 0; i < pagesize; i++) {
    423     uint8_t* buf1 = &memory1[pagesize-i];
    424     uint8_t* buf2 = &memory2[pagesize-i];
    425 
    426     test_cmp_func(buf1, buf2, i);
    427   }
    428 
    429   // Don't cycle through pagesize, MISCMP_MAX_LENGTH bytes should be good.
    430   size_t miscmp_len;
    431   if (pagesize > MISCMP_MAX_LENGTH) {
    432     miscmp_len = MISCMP_MAX_LENGTH;
    433   } else {
    434     miscmp_len = pagesize;
    435   }
    436   for (size_t i = 1; i < miscmp_len; i++) {
    437     uint8_t* buf1 = &memory1[pagesize-i];
    438     for (size_t j = 1; j < miscmp_len; j++) {
    439       if (j == i)
    440         continue;
    441 
    442       uint8_t* buf2 = &memory2[pagesize-j];
    443 
    444       test_miscmp_func(buf1, buf2, i, j);
    445     }
    446   }
    447 
    448   ASSERT_TRUE(mprotect(&memory1[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
    449   ASSERT_TRUE(mprotect(&memory2[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
    450   free(memory1);
    451   free(memory2);
    452 }
    453