MrSlippery

KLEE, the involuntary base64 decoder

Nov 26th, 2015
374
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.99 KB | None | 0 0
  1. #include <klee/klee.h>
  2.  
  3. int same(char *a, char *b, size_t size)
  4. {
  5.   size_t i;
  6.   for (i = 0; i < size; i++) {
  7.     if (a[i] != b[i]) {
  8.       return 0;
  9.     }
  10.   }
  11.   return 1;
  12. }
  13.  
  14. int base64encode(const void* data_buf, size_t dataLength, char* result, size_t* rsultSize);
  15.  
  16. int main(int argc, char *argv[])
  17. {
  18.   int error;
  19.   size_t src_len = 14;
  20.   char *src = "Hello, world!";
  21.   char dest[30];
  22.   size_t dest_size;
  23.   char new_dest[30];
  24.   size_t new_dest_size;
  25.   char new_src[14]; /* <-- Keep your eye on the ball */
  26.  
  27.   /* Encode src to dest */  
  28.   base64encode(src, src_len, dest, &dest_size);
  29.  
  30.   /* Tell KLEE to go wild on the new_src */
  31.   klee_make_symbolic(new_src, src_len, "new_src");
  32.  
  33.   /* Encode new_src to new_dest */
  34.   error = base64encode(new_src, src_len, new_dest, &new_dest_size);
  35.  
  36.   /* No way the result would be the same as for src, right? */
  37.   klee_assert(!(!error &&
  38.                 new_dest_size == dest_size &&
  39.                 same(new_dest, dest, new_dest_size)));
  40. }
  41.  
  42. /* Base64 encoder from here:
  43.  * https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64#C
  44.  * Minor change to return encoded size in *rsultSize (just for convenience).
  45.  */
  46. int base64encode(const void* data_buf, size_t dataLength, char* result, size_t* rsultSize)
  47. {
  48.    size_t resultSize = *rsultSize;
  49.    const char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  50.    const uint8_t *data = (const uint8_t *)data_buf;
  51.    size_t resultIndex = 0;
  52.    size_t x;
  53.    uint32_t n = 0;
  54.    int padCount = dataLength % 3;
  55.    uint8_t n0, n1, n2, n3;
  56.  
  57.    /* increment over the length of the string, three characters at a time */
  58.    for (x = 0; x < dataLength; x += 3)
  59.    {
  60.       /* these three 8-bit (ASCII) characters become one 24-bit number */
  61.       n = ((uint32_t)data[x]) << 16; //parenthesis needed, compiler depending on flags can do the shifting before conversion to uint32_t, resulting to 0
  62.      
  63.       if((x+1) < dataLength)
  64.          n += ((uint32_t)data[x+1]) << 8;//parenthesis needed, compiler depending on flags can do the shifting before conversion to uint32_t, resulting to 0
  65.      
  66.       if((x+2) < dataLength)
  67.          n += data[x+2];
  68.  
  69.       /* this 24-bit number gets separated into four 6-bit numbers */
  70.       n0 = (uint8_t)(n >> 18) & 63;
  71.       n1 = (uint8_t)(n >> 12) & 63;
  72.       n2 = (uint8_t)(n >> 6) & 63;
  73.       n3 = (uint8_t)n & 63;
  74.            
  75.       /*
  76.        * if we have one byte available, then its encoding is spread
  77.        * out over two characters
  78.        */
  79.       if(resultIndex >= resultSize) return 1;   /* indicate failure: buffer too small */
  80.       result[resultIndex++] = base64chars[n0];
  81.       if(resultIndex >= resultSize) return 1;   /* indicate failure: buffer too small */
  82.       result[resultIndex++] = base64chars[n1];
  83.  
  84.       /*
  85.        * if we have only two bytes available, then their encoding is
  86.        * spread out over three chars
  87.        */
  88.       if((x+1) < dataLength)
  89.       {
  90.          if(resultIndex >= resultSize) return 1;   /* indicate failure: buffer too small */
  91.          result[resultIndex++] = base64chars[n2];
  92.       }
  93.  
  94.       /*
  95.        * if we have all three bytes available, then their encoding is spread
  96.        * out over four characters
  97.        */
  98.       if((x+2) < dataLength)
  99.       {
  100.          if(resultIndex >= resultSize) return 1;   /* indicate failure: buffer too small */
  101.          result[resultIndex++] = base64chars[n3];
  102.       }
  103.    }  
  104.  
  105.    /*
  106.     * create and add padding that is required if we did not have a multiple of 3
  107.     * number of characters available
  108.     */
  109.    if (padCount > 0)
  110.    {
  111.       for (; padCount < 3; padCount++)
  112.       {
  113.          if(resultIndex >= resultSize) return 1;   /* indicate failure: buffer too small */
  114.          result[resultIndex++] = '=';
  115.       }
  116.    }
  117.    if(resultIndex >= resultSize) return 1;   /* indicate failure: buffer too small */
  118.    result[resultIndex] = 0;
  119.    *rsultSize = resultIndex + 1;
  120.    return 0;   /* indicate success */
  121. }
Advertisement
Add Comment
Please, Sign In to add comment