/lib/libkrb5/util/support/t_k5buf.c

https://github.com/rhuitl/uClinux · C · 287 lines · 214 code · 31 blank · 42 comment · 96 complexity · aa7c315870acab71421225bbe83f880c MD5 · raw file

  1. /* -*- mode: c; indent-tabs-mode: nil -*- */
  2. /*
  3. * t_k5buf.c
  4. *
  5. * Copyright 2008 Massachusetts Institute of Technology.
  6. * All Rights Reserved.
  7. *
  8. * Export of this software from the United States of America may
  9. * require a specific license from the United States Government.
  10. * It is the responsibility of any person or organization contemplating
  11. * export to obtain such a license before exporting.
  12. *
  13. * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  14. * distribute this software and its documentation for any purpose and
  15. * without fee is hereby granted, provided that the above copyright
  16. * notice appear in all copies and that both that copyright notice and
  17. * this permission notice appear in supporting documentation, and that
  18. * the name of M.I.T. not be used in advertising or publicity pertaining
  19. * to distribution of the software without specific, written prior
  20. * permission. Furthermore if you modify this software you must label
  21. * your software as modified software and not distribute it in such a
  22. * fashion that it might be confused with the original M.I.T. software.
  23. * M.I.T. makes no representations about the suitability of
  24. * this software for any purpose. It is provided "as is" without express
  25. * or implied warranty.
  26. *
  27. * Test the k5buf string buffer module.
  28. */
  29. #include "k5buf-int.h"
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. static void fail_if(int condition, const char *name)
  33. {
  34. if (condition) {
  35. fprintf(stderr, "%s failed\n", name);
  36. exit(1);
  37. }
  38. }
  39. /* Test the invariants of a buffer. */
  40. static void check_buf(struct k5buf *buf, const char *name)
  41. {
  42. fail_if(buf->buftype != FIXED && buf->buftype != DYNAMIC
  43. && buf->buftype != ERROR, name);
  44. if (buf->buftype == ERROR)
  45. return;
  46. fail_if(buf->space == 0, name);
  47. fail_if(buf->space > SPACE_MAX, name);
  48. fail_if(buf->len >= buf->space, name);
  49. fail_if(buf->data[buf->len] != 0, name);
  50. }
  51. static void test_basic()
  52. {
  53. struct k5buf buf;
  54. char storage[1024], *s;
  55. ssize_t len;
  56. krb5int_buf_init_fixed(&buf, storage, sizeof(storage));
  57. krb5int_buf_add(&buf, "Hello ");
  58. krb5int_buf_add_len(&buf, "world", 5);
  59. check_buf(&buf, "basic fixed");
  60. s = krb5int_buf_data(&buf);
  61. len = krb5int_buf_len(&buf);
  62. fail_if(!s || strcmp(s, "Hello world") != 0 || len != 11, "basic fixed");
  63. krb5int_buf_init_dynamic(&buf);
  64. krb5int_buf_add_len(&buf, "Hello", 5);
  65. krb5int_buf_add(&buf, " world");
  66. check_buf(&buf, "basic dynamic");
  67. s = krb5int_buf_data(&buf);
  68. len = krb5int_buf_len(&buf);
  69. fail_if(!s || strcmp(s, "Hello world") != 0 || len != 11, "basic dynamic");
  70. krb5int_free_buf(&buf);
  71. }
  72. static void test_realloc()
  73. {
  74. struct k5buf buf;
  75. char data[1024], *s;
  76. ssize_t len;
  77. size_t i;
  78. for (i = 0; i < sizeof(data); i++)
  79. data[i] = 'a';
  80. /* Cause the buffer size to double from 128 to 256 bytes. */
  81. krb5int_buf_init_dynamic(&buf);
  82. krb5int_buf_add_len(&buf, data, 10);
  83. krb5int_buf_add_len(&buf, data, 128);
  84. fail_if(buf.space != 256, "realloc 1");
  85. check_buf(&buf, "realloc 1");
  86. s = krb5int_buf_data(&buf);
  87. len = krb5int_buf_len(&buf);
  88. fail_if(!s || len != 138 || memcmp(s, data, len) != 0, "realloc 1");
  89. /* Cause the same buffer to double in size to 512 bytes. */
  90. krb5int_buf_add_len(&buf, data, 128);
  91. fail_if(buf.space != 512, "realloc 2");
  92. check_buf(&buf, "realloc 2");
  93. s = krb5int_buf_data(&buf);
  94. len = krb5int_buf_len(&buf);
  95. fail_if(!s || len != 266 || memcmp(s, data, len) != 0, "realloc 2");
  96. krb5int_free_buf(&buf);
  97. /* Cause a buffer to increase from 128 to 512 bytes directly. */
  98. krb5int_buf_init_dynamic(&buf);
  99. krb5int_buf_add_len(&buf, data, 10);
  100. krb5int_buf_add_len(&buf, data, 256);
  101. fail_if(buf.space != 512, "realloc 3");
  102. check_buf(&buf, "realloc 3");
  103. s = krb5int_buf_data(&buf);
  104. len = krb5int_buf_len(&buf);
  105. fail_if(!s || len != 266 || memcmp(s, data, len) != 0, "realloc 3");
  106. krb5int_free_buf(&buf);
  107. /* Cause a buffer to increase from 128 to 1024 bytes directly. */
  108. krb5int_buf_init_dynamic(&buf);
  109. krb5int_buf_add_len(&buf, data, 10);
  110. krb5int_buf_add_len(&buf, data, 512);
  111. fail_if(buf.space != 1024, "realloc 4");
  112. check_buf(&buf, "realloc 4");
  113. s = krb5int_buf_data(&buf);
  114. len = krb5int_buf_len(&buf);
  115. fail_if(!s || len != 522 || memcmp(s, data, len) != 0, "realloc 4");
  116. krb5int_free_buf(&buf);
  117. /* Cause a reallocation to fail by exceeding SPACE_MAX. */
  118. krb5int_buf_init_dynamic(&buf);
  119. krb5int_buf_add_len(&buf, data, 10);
  120. krb5int_buf_add_len(&buf, NULL, SPACE_MAX);
  121. check_buf(&buf, "realloc 5");
  122. s = krb5int_buf_data(&buf);
  123. len = krb5int_buf_len(&buf);
  124. fail_if(buf.buftype != ERROR || s != NULL || len != -1, "realloc 5");
  125. krb5int_free_buf(&buf);
  126. /* Cause a reallocation to fail by integer overflow. */
  127. krb5int_buf_init_dynamic(&buf);
  128. krb5int_buf_add_len(&buf, data, 100);
  129. krb5int_buf_add_len(&buf, NULL, SPACE_MAX * 2);
  130. check_buf(&buf, "realloc 6");
  131. s = krb5int_buf_data(&buf);
  132. len = krb5int_buf_len(&buf);
  133. fail_if(buf.buftype != ERROR || s != NULL || len != -1, "realloc 6");
  134. krb5int_free_buf(&buf);
  135. }
  136. static void test_overflow()
  137. {
  138. struct k5buf buf;
  139. char storage[10], *s;
  140. ssize_t len;
  141. /* Cause a fixed-sized buffer overflow. */
  142. krb5int_buf_init_fixed(&buf, storage, sizeof(storage));
  143. krb5int_buf_add(&buf, "12345");
  144. krb5int_buf_add(&buf, "12345");
  145. check_buf(&buf, "overflow 1");
  146. s = krb5int_buf_data(&buf);
  147. len = krb5int_buf_len(&buf);
  148. fail_if(buf.buftype != ERROR || s != NULL || len != -1, "overflow 1");
  149. /* Cause a fixed-sized buffer overflow with integer overflow. */
  150. krb5int_buf_init_fixed(&buf, storage, sizeof(storage));
  151. krb5int_buf_add(&buf, "12345");
  152. krb5int_buf_add_len(&buf, NULL, SPACE_MAX * 2);
  153. check_buf(&buf, "overflow 2");
  154. s = krb5int_buf_data(&buf);
  155. len = krb5int_buf_len(&buf);
  156. fail_if(buf.buftype != ERROR || s != NULL || len != -1, "overflow 2");
  157. }
  158. static void test_error()
  159. {
  160. struct k5buf buf;
  161. char storage[1];
  162. /* Cause an overflow and then perform actions afterwards. */
  163. krb5int_buf_init_fixed(&buf, storage, sizeof(storage));
  164. krb5int_buf_add(&buf, "1");
  165. fail_if(buf.buftype != ERROR, "error");
  166. check_buf(&buf, "error");
  167. krb5int_buf_add(&buf, "test");
  168. check_buf(&buf, "error");
  169. krb5int_buf_add_len(&buf, "test", 4);
  170. check_buf(&buf, "error");
  171. krb5int_buf_truncate(&buf, 3);
  172. check_buf(&buf, "error");
  173. fail_if(buf.buftype != ERROR, "error");
  174. }
  175. static void test_truncate()
  176. {
  177. struct k5buf buf;
  178. char *s;
  179. ssize_t len;
  180. krb5int_buf_init_dynamic(&buf);
  181. krb5int_buf_add(&buf, "abcde");
  182. krb5int_buf_add(&buf, "fghij");
  183. krb5int_buf_truncate(&buf, 7);
  184. check_buf(&buf, "truncate");
  185. s = krb5int_buf_data(&buf);
  186. len = krb5int_buf_len(&buf);
  187. fail_if(!s || len != 7 || strcmp(s, "abcdefg") != 0, "truncate");
  188. krb5int_free_buf(&buf);
  189. }
  190. static void test_binary()
  191. {
  192. struct k5buf buf;
  193. char *s, data[] = { 'a', 0, 'b' };
  194. ssize_t len;
  195. krb5int_buf_init_dynamic(&buf);
  196. krb5int_buf_add_len(&buf, data, 3);
  197. krb5int_buf_add_len(&buf, data, 3);
  198. check_buf(&buf, "binary");
  199. s = krb5int_buf_data(&buf);
  200. len = krb5int_buf_len(&buf);
  201. fail_if(!s || len != 6, "binary");
  202. fail_if(s[0] != 'a' || s[1] != 0 || s[2] != 'b', "binary");
  203. fail_if(s[3] != 'a' || s[4] != 0 || s[5] != 'b', "binary");
  204. krb5int_free_buf(&buf);
  205. }
  206. static void test_fmt()
  207. {
  208. struct k5buf buf;
  209. char *s, storage[10], data[1024];
  210. ssize_t len;
  211. size_t i;
  212. for (i = 0; i < sizeof(data) - 1; i++)
  213. data[i] = 'a';
  214. data[i] = '\0';
  215. /* Format some text into a non-empty fixed buffer. */
  216. krb5int_buf_init_fixed(&buf, storage, sizeof(storage));
  217. krb5int_buf_add(&buf, "foo");
  218. krb5int_buf_add_fmt(&buf, " %d ", 3);
  219. check_buf(&buf, "fmt 1");
  220. s = krb5int_buf_data(&buf);
  221. len = krb5int_buf_len(&buf);
  222. fail_if(!s || len != 6 || strcmp(s, "foo 3 ") != 0, "fmt 1");
  223. /* Overflow the same buffer with formatted text. */
  224. krb5int_buf_add_fmt(&buf, "%d%d%d%d", 1, 2, 3, 4);
  225. check_buf(&buf, "fmt 2");
  226. s = krb5int_buf_data(&buf);
  227. len = krb5int_buf_len(&buf);
  228. fail_if(buf.buftype != ERROR || s != NULL || len != -1, "fmt 2");
  229. /* Format some text into a non-empty dynamic buffer. */
  230. krb5int_buf_init_dynamic(&buf);
  231. krb5int_buf_add(&buf, "foo");
  232. krb5int_buf_add_fmt(&buf, " %d ", 3);
  233. check_buf(&buf, "fmt 3");
  234. s = krb5int_buf_data(&buf);
  235. len = krb5int_buf_len(&buf);
  236. fail_if(!s || len != 6 || strcmp(s, "foo 3 ") != 0, "fmt 3");
  237. /* Format more text into the same buffer, causing a big resize. */
  238. krb5int_buf_add_fmt(&buf, "%s", data);
  239. check_buf(&buf, "fmt 4");
  240. fail_if(buf.space != 2048, "fmt 4");
  241. s = krb5int_buf_data(&buf);
  242. len = krb5int_buf_len(&buf);
  243. fail_if(!s || len != 1029 || strcmp(s + 6, data) != 0, "fmt 4");
  244. krb5int_free_buf(&buf);
  245. }
  246. int main()
  247. {
  248. test_basic();
  249. test_realloc();
  250. test_overflow();
  251. test_error();
  252. test_truncate();
  253. test_binary();
  254. test_fmt();
  255. return 0;
  256. }