test_buffers.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. /* Copyright (c) 2001-2004, Roger Dingledine.
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2017, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #define BUFFERS_PRIVATE
  6. #define PROTO_HTTP_PRIVATE
  7. #include "or.h"
  8. #include "buffers.h"
  9. #include "buffers_tls.h"
  10. #include "ext_orport.h"
  11. #include "proto_cell.h"
  12. #include "proto_ext_or.h"
  13. #include "proto_http.h"
  14. #include "proto_control0.h"
  15. #include "proto_socks.h"
  16. #include "test.h"
  17. /** Run unit tests for buffers.c */
  18. static void
  19. test_buffers_basic(void *arg)
  20. {
  21. char str[256];
  22. char str2[256];
  23. buf_t *buf = NULL, *buf2 = NULL;
  24. const char *cp;
  25. int j;
  26. size_t r;
  27. (void) arg;
  28. /****
  29. * buf_new
  30. ****/
  31. if (!(buf = buf_new()))
  32. TT_DIE(("Assertion failed."));
  33. //test_eq(buf_capacity(buf), 4096);
  34. tt_int_op(buf_datalen(buf),OP_EQ, 0);
  35. /****
  36. * General pointer frobbing
  37. */
  38. for (j=0;j<256;++j) {
  39. str[j] = (char)j;
  40. }
  41. buf_add(buf, str, 256);
  42. buf_add(buf, str, 256);
  43. tt_int_op(buf_datalen(buf),OP_EQ, 512);
  44. buf_get_bytes(buf, str2, 200);
  45. tt_mem_op(str,OP_EQ, str2, 200);
  46. tt_int_op(buf_datalen(buf),OP_EQ, 312);
  47. memset(str2, 0, sizeof(str2));
  48. buf_get_bytes(buf, str2, 256);
  49. tt_mem_op(str+200,OP_EQ, str2, 56);
  50. tt_mem_op(str,OP_EQ, str2+56, 200);
  51. tt_int_op(buf_datalen(buf),OP_EQ, 56);
  52. memset(str2, 0, sizeof(str2));
  53. /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add
  54. * another 3584 bytes, we hit the end. */
  55. for (j=0;j<15;++j) {
  56. buf_add(buf, str, 256);
  57. }
  58. buf_assert_ok(buf);
  59. tt_int_op(buf_datalen(buf),OP_EQ, 3896);
  60. buf_get_bytes(buf, str2, 56);
  61. tt_int_op(buf_datalen(buf),OP_EQ, 3840);
  62. tt_mem_op(str+200,OP_EQ, str2, 56);
  63. for (j=0;j<15;++j) {
  64. memset(str2, 0, sizeof(str2));
  65. buf_get_bytes(buf, str2, 256);
  66. tt_mem_op(str,OP_EQ, str2, 256);
  67. }
  68. tt_int_op(buf_datalen(buf),OP_EQ, 0);
  69. buf_free(buf);
  70. buf = NULL;
  71. /* Okay, now make sure growing can work. */
  72. buf = buf_new_with_capacity(16);
  73. //test_eq(buf_capacity(buf), 16);
  74. buf_add(buf, str+1, 255);
  75. //test_eq(buf_capacity(buf), 256);
  76. buf_get_bytes(buf, str2, 254);
  77. tt_mem_op(str+1,OP_EQ, str2, 254);
  78. //test_eq(buf_capacity(buf), 256);
  79. buf_assert_ok(buf);
  80. buf_add(buf, str, 32);
  81. //test_eq(buf_capacity(buf), 256);
  82. buf_assert_ok(buf);
  83. buf_add(buf, str, 256);
  84. buf_assert_ok(buf);
  85. //test_eq(buf_capacity(buf), 512);
  86. tt_int_op(buf_datalen(buf),OP_EQ, 33+256);
  87. buf_get_bytes(buf, str2, 33);
  88. tt_int_op(*str2,OP_EQ, str[255]);
  89. tt_mem_op(str2+1,OP_EQ, str, 32);
  90. //test_eq(buf_capacity(buf), 512);
  91. tt_int_op(buf_datalen(buf),OP_EQ, 256);
  92. buf_get_bytes(buf, str2, 256);
  93. tt_mem_op(str,OP_EQ, str2, 256);
  94. /* now try shrinking: case 1. */
  95. buf_free(buf);
  96. buf = buf_new_with_capacity(33668);
  97. for (j=0;j<67;++j) {
  98. buf_add(buf, str,255);
  99. }
  100. //test_eq(buf_capacity(buf), 33668);
  101. tt_int_op(buf_datalen(buf),OP_EQ, 17085);
  102. for (j=0; j < 40; ++j) {
  103. buf_get_bytes(buf, str2, 255);
  104. tt_mem_op(str2,OP_EQ, str, 255);
  105. }
  106. /* now try shrinking: case 2. */
  107. buf_free(buf);
  108. buf = buf_new_with_capacity(33668);
  109. for (j=0;j<67;++j) {
  110. buf_add(buf, str, 255);
  111. }
  112. for (j=0; j < 20; ++j) {
  113. buf_get_bytes(buf, str2, 255);
  114. tt_mem_op(str2,OP_EQ, str, 255);
  115. }
  116. for (j=0;j<80;++j) {
  117. buf_add(buf, str, 255);
  118. }
  119. //test_eq(buf_capacity(buf),33668);
  120. for (j=0; j < 120; ++j) {
  121. buf_get_bytes(buf, str2, 255);
  122. tt_mem_op(str2,OP_EQ, str, 255);
  123. }
  124. /* Move from buf to buf. */
  125. buf_free(buf);
  126. buf = buf_new_with_capacity(4096);
  127. buf2 = buf_new_with_capacity(4096);
  128. for (j=0;j<100;++j)
  129. buf_add(buf, str, 255);
  130. tt_int_op(buf_datalen(buf),OP_EQ, 25500);
  131. for (j=0;j<100;++j) {
  132. r = 10;
  133. buf_move_to_buf(buf2, buf, &r);
  134. tt_int_op(r,OP_EQ, 0);
  135. }
  136. tt_int_op(buf_datalen(buf),OP_EQ, 24500);
  137. tt_int_op(buf_datalen(buf2),OP_EQ, 1000);
  138. for (j=0;j<3;++j) {
  139. buf_get_bytes(buf2, str2, 255);
  140. tt_mem_op(str2,OP_EQ, str, 255);
  141. }
  142. r = 8192; /*big move*/
  143. buf_move_to_buf(buf2, buf, &r);
  144. tt_int_op(r,OP_EQ, 0);
  145. r = 30000; /* incomplete move */
  146. buf_move_to_buf(buf2, buf, &r);
  147. tt_int_op(r,OP_EQ, 13692);
  148. for (j=0;j<97;++j) {
  149. buf_get_bytes(buf2, str2, 255);
  150. tt_mem_op(str2,OP_EQ, str, 255);
  151. }
  152. buf_free(buf);
  153. buf_free(buf2);
  154. buf = buf2 = NULL;
  155. buf = buf_new_with_capacity(5);
  156. cp = "Testing. This is a moderately long Testing string.";
  157. for (j = 0; cp[j]; j++)
  158. buf_add(buf, cp+j, 1);
  159. tt_int_op(0,OP_EQ, buf_find_string_offset(buf, "Testing", 7));
  160. tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "esting", 6));
  161. tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "est", 3));
  162. tt_int_op(39,OP_EQ, buf_find_string_offset(buf, "ing str", 7));
  163. tt_int_op(35,OP_EQ, buf_find_string_offset(buf, "Testing str", 11));
  164. tt_int_op(32,OP_EQ, buf_find_string_offset(buf, "ng ", 3));
  165. tt_int_op(43,OP_EQ, buf_find_string_offset(buf, "string.", 7));
  166. tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "shrdlu", 6));
  167. tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "Testing thing", 13));
  168. tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "ngx", 3));
  169. buf_free(buf);
  170. buf = NULL;
  171. /* Try adding a string too long for any freelist. */
  172. {
  173. char *mem = tor_malloc_zero(65536);
  174. buf = buf_new();
  175. buf_add(buf, mem, 65536);
  176. tor_free(mem);
  177. tt_int_op(buf_datalen(buf), OP_EQ, 65536);
  178. buf_free(buf);
  179. buf = NULL;
  180. }
  181. done:
  182. if (buf)
  183. buf_free(buf);
  184. if (buf2)
  185. buf_free(buf2);
  186. }
  187. static void
  188. test_buffer_pullup(void *arg)
  189. {
  190. buf_t *buf;
  191. char *stuff, *tmp;
  192. const char *cp;
  193. size_t sz;
  194. (void)arg;
  195. stuff = tor_malloc(16384);
  196. tmp = tor_malloc(16384);
  197. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  198. tt_assert(buf);
  199. tt_int_op(buf_get_default_chunk_size(buf), OP_EQ, 4096);
  200. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  201. /* There are a bunch of cases for pullup. One is the trivial case. Let's
  202. mess around with an empty buffer. */
  203. buf_pullup(buf, 16, &cp, &sz);
  204. tt_ptr_op(cp, OP_EQ, NULL);
  205. tt_uint_op(sz, OP_EQ, 0);
  206. /* Let's make sure nothing got allocated */
  207. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  208. /* Case 1: everything puts into the first chunk with some moving. */
  209. /* Let's add some data. */
  210. crypto_rand(stuff, 16384);
  211. buf_add(buf, stuff, 3000);
  212. buf_add(buf, stuff+3000, 3000);
  213. buf_pullup(buf, 0, &cp, &sz);
  214. tt_ptr_op(cp, OP_NE, NULL);
  215. tt_int_op(sz, OP_LE, 4096);
  216. /* Make room for 3000 bytes in the first chunk, so that the pullup-move code
  217. * can get tested. */
  218. tt_int_op(buf_get_bytes(buf, tmp, 3000), OP_EQ, 3000);
  219. tt_mem_op(tmp,OP_EQ, stuff, 3000);
  220. buf_pullup(buf, 2048, &cp, &sz);
  221. buf_assert_ok(buf);
  222. tt_ptr_op(cp, OP_NE, NULL);
  223. tt_int_op(sz, OP_GE, 2048);
  224. tt_mem_op(cp,OP_EQ, stuff+3000, 2048);
  225. tt_int_op(3000, OP_EQ, buf_datalen(buf));
  226. tt_int_op(buf_get_bytes(buf, tmp, 3000), OP_EQ, 0);
  227. tt_mem_op(tmp,OP_EQ, stuff+3000, 2048);
  228. buf_free(buf);
  229. /* Now try the large-chunk case. */
  230. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  231. buf_add(buf, stuff, 4000);
  232. buf_add(buf, stuff+4000, 4000);
  233. buf_add(buf, stuff+8000, 4000);
  234. buf_add(buf, stuff+12000, 4000);
  235. tt_int_op(buf_datalen(buf), OP_EQ, 16000);
  236. buf_pullup(buf, 0, &cp, &sz);
  237. tt_ptr_op(cp, OP_NE, NULL);
  238. tt_int_op(sz, OP_LE, 4096);
  239. buf_pullup(buf, 12500, &cp, &sz);
  240. buf_assert_ok(buf);
  241. tt_ptr_op(cp, OP_NE, NULL);
  242. tt_int_op(sz, OP_GE, 12500);
  243. tt_mem_op(cp,OP_EQ, stuff, 12500);
  244. tt_int_op(buf_datalen(buf), OP_EQ, 16000);
  245. buf_get_bytes(buf, tmp, 12400);
  246. tt_mem_op(tmp,OP_EQ, stuff, 12400);
  247. tt_int_op(buf_datalen(buf), OP_EQ, 3600);
  248. buf_get_bytes(buf, tmp, 3500);
  249. tt_mem_op(tmp,OP_EQ, stuff+12400, 3500);
  250. buf_get_bytes(buf, tmp, 100);
  251. tt_mem_op(tmp,OP_EQ, stuff+15900, 10);
  252. buf_free(buf);
  253. /* Make sure that the pull-up-whole-buffer case works */
  254. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  255. buf_add(buf, stuff, 4000);
  256. buf_add(buf, stuff+4000, 4000);
  257. buf_get_bytes(buf, tmp, 100); /* dump 100 bytes from first chunk */
  258. buf_pullup(buf, 16000, &cp, &sz);
  259. buf_assert_ok(buf);
  260. tt_ptr_op(cp, OP_NE, NULL);
  261. tt_int_op(sz, OP_EQ, 7900);
  262. tt_mem_op(cp,OP_EQ, stuff+100, 7900);
  263. buf_free(buf);
  264. buf = NULL;
  265. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  266. done:
  267. buf_free(buf);
  268. tor_free(stuff);
  269. tor_free(tmp);
  270. }
  271. static void
  272. test_buffer_copy(void *arg)
  273. {
  274. buf_t *buf=NULL, *buf2=NULL;
  275. const char *s;
  276. size_t len;
  277. char b[256];
  278. int i;
  279. (void)arg;
  280. buf = buf_new();
  281. tt_assert(buf);
  282. /* Copy an empty buffer. */
  283. tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
  284. tt_assert(buf2);
  285. tt_int_op(0, OP_EQ, buf_datalen(buf2));
  286. /* Now try with a short buffer. */
  287. s = "And now comes an act of enormous enormance!";
  288. len = strlen(s);
  289. buf_add(buf, s, len);
  290. tt_int_op(len, OP_EQ, buf_datalen(buf));
  291. /* Add junk to buf2 so we can test replacing.*/
  292. buf_add(buf2, "BLARG", 5);
  293. tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
  294. tt_int_op(len, OP_EQ, buf_datalen(buf2));
  295. buf_get_bytes(buf2, b, len);
  296. tt_mem_op(b, OP_EQ, s, len);
  297. /* Now free buf2 and retry so we can test allocating */
  298. buf_free(buf2);
  299. buf2 = NULL;
  300. tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
  301. tt_int_op(len, OP_EQ, buf_datalen(buf2));
  302. buf_get_bytes(buf2, b, len);
  303. tt_mem_op(b, OP_EQ, s, len);
  304. /* Clear buf for next test */
  305. buf_get_bytes(buf, b, len);
  306. tt_int_op(buf_datalen(buf),OP_EQ,0);
  307. /* Okay, now let's try a bigger buffer. */
  308. s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit "
  309. "esse quam nihil molestiae consequatur, vel illum qui dolorem eum "
  310. "fugiat quo voluptas nulla pariatur?";
  311. len = strlen(s);
  312. for (i = 0; i < 256; ++i) {
  313. b[0]=i;
  314. buf_add(buf, b, 1);
  315. buf_add(buf, s, len);
  316. }
  317. tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
  318. tt_int_op(buf_datalen(buf2), OP_EQ, buf_datalen(buf));
  319. for (i = 0; i < 256; ++i) {
  320. buf_get_bytes(buf2, b, len+1);
  321. tt_int_op((unsigned char)b[0],OP_EQ,i);
  322. tt_mem_op(b+1, OP_EQ, s, len);
  323. }
  324. done:
  325. if (buf)
  326. buf_free(buf);
  327. if (buf2)
  328. buf_free(buf2);
  329. }
  330. static void
  331. test_buffer_ext_or_cmd(void *arg)
  332. {
  333. ext_or_cmd_t *cmd = NULL;
  334. buf_t *buf = buf_new();
  335. char *tmp = NULL;
  336. (void) arg;
  337. /* Empty -- should give "not there. */
  338. tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  339. tt_ptr_op(NULL, OP_EQ, cmd);
  340. /* Three bytes: shouldn't work. */
  341. buf_add(buf, "\x00\x20\x00", 3);
  342. tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  343. tt_ptr_op(NULL, OP_EQ, cmd);
  344. tt_int_op(3, OP_EQ, buf_datalen(buf));
  345. /* 0020 0000: That's a nil command. It should work. */
  346. buf_add(buf, "\x00", 1);
  347. tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  348. tt_ptr_op(NULL, OP_NE, cmd);
  349. tt_int_op(0x20, OP_EQ, cmd->cmd);
  350. tt_int_op(0, OP_EQ, cmd->len);
  351. tt_int_op(0, OP_EQ, buf_datalen(buf));
  352. ext_or_cmd_free(cmd);
  353. cmd = NULL;
  354. /* Now try a length-6 command with one byte missing. */
  355. buf_add(buf, "\x10\x21\x00\x06""abcde", 9);
  356. tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  357. tt_ptr_op(NULL, OP_EQ, cmd);
  358. buf_add(buf, "f", 1);
  359. tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  360. tt_ptr_op(NULL, OP_NE, cmd);
  361. tt_int_op(0x1021, OP_EQ, cmd->cmd);
  362. tt_int_op(6, OP_EQ, cmd->len);
  363. tt_mem_op("abcdef", OP_EQ, cmd->body, 6);
  364. tt_int_op(0, OP_EQ, buf_datalen(buf));
  365. ext_or_cmd_free(cmd);
  366. cmd = NULL;
  367. /* Now try a length-10 command with 4 extra bytes. */
  368. buf_add(buf, "\xff\xff\x00\x0aloremipsum\x10\x00\xff\xff", 18);
  369. tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  370. tt_ptr_op(NULL, OP_NE, cmd);
  371. tt_int_op(0xffff, OP_EQ, cmd->cmd);
  372. tt_int_op(10, OP_EQ, cmd->len);
  373. tt_mem_op("loremipsum", OP_EQ, cmd->body, 10);
  374. tt_int_op(4, OP_EQ, buf_datalen(buf));
  375. ext_or_cmd_free(cmd);
  376. cmd = NULL;
  377. /* Finally, let's try a maximum-length command. We already have the header
  378. * waiting. */
  379. tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  380. tmp = tor_malloc_zero(65535);
  381. buf_add(buf, tmp, 65535);
  382. tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  383. tt_ptr_op(NULL, OP_NE, cmd);
  384. tt_int_op(0x1000, OP_EQ, cmd->cmd);
  385. tt_int_op(0xffff, OP_EQ, cmd->len);
  386. tt_mem_op(tmp, OP_EQ, cmd->body, 65535);
  387. tt_int_op(0, OP_EQ, buf_datalen(buf));
  388. ext_or_cmd_free(cmd);
  389. cmd = NULL;
  390. done:
  391. ext_or_cmd_free(cmd);
  392. buf_free(buf);
  393. tor_free(tmp);
  394. }
  395. static void
  396. test_buffer_allocation_tracking(void *arg)
  397. {
  398. char *junk = tor_malloc(16384);
  399. buf_t *buf1 = NULL, *buf2 = NULL;
  400. int i;
  401. (void)arg;
  402. crypto_rand(junk, 16384);
  403. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  404. buf1 = buf_new();
  405. tt_assert(buf1);
  406. buf2 = buf_new();
  407. tt_assert(buf2);
  408. tt_int_op(buf_allocation(buf1), OP_EQ, 0);
  409. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  410. buf_add(buf1, junk, 4000);
  411. buf_add(buf1, junk, 4000);
  412. buf_add(buf1, junk, 4000);
  413. buf_add(buf1, junk, 4000);
  414. tt_int_op(buf_allocation(buf1), OP_EQ, 16384);
  415. buf_get_bytes(buf1, junk, 100);
  416. tt_int_op(buf_allocation(buf1), OP_EQ, 16384); /* still 4 4k chunks */
  417. tt_int_op(buf_get_total_allocation(), OP_EQ, 16384);
  418. buf_get_bytes(buf1, junk, 4096); /* drop a 1k chunk... */
  419. tt_int_op(buf_allocation(buf1), OP_EQ, 3*4096); /* now 3 4k chunks */
  420. tt_int_op(buf_get_total_allocation(), OP_EQ, 12288); /* that chunk was really
  421. freed. */
  422. buf_add(buf2, junk, 4000);
  423. tt_int_op(buf_allocation(buf2), OP_EQ, 4096); /* another 4k chunk. */
  424. /*
  425. * We bounce back up to 16384 by allocating a new chunk.
  426. */
  427. tt_int_op(buf_get_total_allocation(), OP_EQ, 16384);
  428. buf_add(buf2, junk, 4000);
  429. tt_int_op(buf_allocation(buf2), OP_EQ, 8192); /* another 4k chunk. */
  430. tt_int_op(buf_get_total_allocation(),
  431. OP_EQ, 5*4096); /* that chunk was new. */
  432. /* Make a really huge buffer */
  433. for (i = 0; i < 1000; ++i) {
  434. buf_add(buf2, junk, 4000);
  435. }
  436. tt_int_op(buf_allocation(buf2), OP_GE, 4008000);
  437. tt_int_op(buf_get_total_allocation(), OP_GE, 4008000);
  438. buf_free(buf2);
  439. buf2 = NULL;
  440. tt_int_op(buf_get_total_allocation(), OP_LT, 4008000);
  441. tt_int_op(buf_get_total_allocation(), OP_EQ, buf_allocation(buf1));
  442. buf_free(buf1);
  443. buf1 = NULL;
  444. tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
  445. done:
  446. buf_free(buf1);
  447. buf_free(buf2);
  448. tor_free(junk);
  449. }
  450. static void
  451. test_buffer_time_tracking(void *arg)
  452. {
  453. buf_t *buf=NULL, *buf2=NULL;
  454. const time_t START = 1389288246;
  455. const uint64_t START_NSEC = ((uint64_t)START) * 1000000000;
  456. int i;
  457. char tmp[4096];
  458. (void)arg;
  459. crypto_rand(tmp, sizeof(tmp));
  460. monotime_enable_test_mocking();
  461. buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  462. tt_assert(buf);
  463. monotime_coarse_set_mock_time_nsec(START_NSEC);
  464. const uint32_t START_MSEC = (uint32_t)monotime_coarse_absolute_msec();
  465. /* Empty buffer means the timestamp is 0. */
  466. tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC));
  467. tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));
  468. buf_add(buf, "ABCDEFG", 7);
  469. tt_int_op(1000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));
  470. buf2 = buf_copy(buf);
  471. tt_assert(buf2);
  472. tt_int_op(1234, OP_EQ,
  473. buf_get_oldest_chunk_timestamp(buf2, START_MSEC+1234));
  474. /* Now add more bytes; enough to overflow the first chunk. */
  475. monotime_coarse_set_mock_time_nsec(START_NSEC + 123 * (uint64_t)1000000);
  476. for (i = 0; i < 600; ++i)
  477. buf_add(buf, "ABCDEFG", 7);
  478. tt_int_op(4207, OP_EQ, buf_datalen(buf));
  479. /* The oldest bytes are still in the front. */
  480. tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));
  481. /* Once those bytes are dropped, the chunk is still on the first
  482. * timestamp. */
  483. buf_get_bytes(buf, tmp, 100);
  484. tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));
  485. /* But once we discard the whole first chunk, we get the data in the second
  486. * chunk. */
  487. buf_get_bytes(buf, tmp, 4000);
  488. tt_int_op(107, OP_EQ, buf_datalen(buf));
  489. tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));
  490. /* This time we'll be grabbing a chunk from the freelist, and making sure
  491. its time gets updated */
  492. monotime_coarse_set_mock_time_nsec(START_NSEC + 5617 * (uint64_t)1000000);
  493. for (i = 0; i < 600; ++i)
  494. buf_add(buf, "ABCDEFG", 7);
  495. tt_int_op(4307, OP_EQ, buf_datalen(buf));
  496. tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));
  497. buf_get_bytes(buf, tmp, 4000);
  498. buf_get_bytes(buf, tmp, 306);
  499. tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617));
  500. tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+6000));
  501. done:
  502. buf_free(buf);
  503. buf_free(buf2);
  504. monotime_disable_test_mocking();
  505. }
  506. static void
  507. test_buffers_compress_fin_at_chunk_end_impl(compress_method_t method,
  508. compression_level_t level)
  509. {
  510. char *msg = NULL;
  511. char *contents = NULL;
  512. char *expanded = NULL;
  513. buf_t *buf = NULL;
  514. tor_compress_state_t *compress_state = NULL;
  515. size_t out_len, in_len;
  516. size_t sz, headerjunk;
  517. buf = buf_new_with_capacity(128); /* will round up */
  518. sz = buf_get_default_chunk_size(buf);
  519. msg = tor_malloc_zero(sz);
  520. buf_add(buf, msg, 1);
  521. tt_assert(buf->head);
  522. /* Fill up the chunk so the compression stuff won't fit in one chunk. */
  523. tt_uint_op(buf->head->memlen, OP_LT, sz);
  524. headerjunk = buf->head->memlen - 7;
  525. buf_add(buf, msg, headerjunk-1);
  526. tt_uint_op(buf->head->datalen, OP_EQ, headerjunk);
  527. tt_uint_op(buf_datalen(buf), OP_EQ, headerjunk);
  528. /* Write an empty string, with finalization on. */
  529. compress_state = tor_compress_new(1, method, level);
  530. tt_int_op(buf_add_compress(buf, compress_state, "", 0, 1), OP_EQ, 0);
  531. in_len = buf_datalen(buf);
  532. contents = tor_malloc(in_len);
  533. tt_int_op(buf_get_bytes(buf, contents, in_len), OP_EQ, 0);
  534. if (method == NO_METHOD) {
  535. tt_uint_op(in_len, OP_EQ, headerjunk);
  536. } else {
  537. tt_uint_op(in_len, OP_GT, headerjunk);
  538. }
  539. tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
  540. contents + headerjunk,
  541. in_len - headerjunk,
  542. method, 1,
  543. LOG_WARN));
  544. tt_int_op(out_len, OP_EQ, 0);
  545. tt_assert(expanded);
  546. done:
  547. buf_free(buf);
  548. tor_compress_free(compress_state);
  549. tor_free(contents);
  550. tor_free(expanded);
  551. tor_free(msg);
  552. }
  553. static void
  554. test_buffers_compress_impl(compress_method_t method,
  555. compression_level_t level,
  556. int finalize_with_nil)
  557. {
  558. char *msg = NULL;
  559. char *contents = NULL;
  560. char *expanded = NULL;
  561. buf_t *buf = NULL;
  562. tor_compress_state_t *compress_state = NULL;
  563. size_t out_len, in_len;
  564. int done;
  565. buf = buf_new_with_capacity(128); /* will round up */
  566. compress_state = tor_compress_new(1, method, level);
  567. msg = tor_malloc(512);
  568. crypto_rand(msg, 512);
  569. tt_int_op(buf_add_compress(buf, compress_state,
  570. msg, 128, 0), OP_EQ, 0);
  571. tt_int_op(buf_add_compress(buf, compress_state,
  572. msg+128, 128, 0), OP_EQ, 0);
  573. tt_int_op(buf_add_compress(buf, compress_state,
  574. msg+256, 256, 0), OP_EQ, 0);
  575. done = !finalize_with_nil;
  576. tt_int_op(buf_add_compress(buf, compress_state,
  577. "all done", 9, done), OP_EQ, 0);
  578. if (finalize_with_nil) {
  579. tt_int_op(buf_add_compress(buf, compress_state, "", 0, 1), OP_EQ, 0);
  580. }
  581. in_len = buf_datalen(buf);
  582. contents = tor_malloc(in_len);
  583. tt_int_op(buf_get_bytes(buf, contents, in_len), OP_EQ, 0);
  584. tt_int_op(0, OP_EQ, tor_uncompress(&expanded, &out_len,
  585. contents, in_len,
  586. method, 1,
  587. LOG_WARN));
  588. tt_int_op(out_len, OP_GE, 128);
  589. tt_mem_op(msg, OP_EQ, expanded, 128);
  590. tt_int_op(out_len, OP_GE, 512);
  591. tt_mem_op(msg, OP_EQ, expanded, 512);
  592. tt_int_op(out_len, OP_EQ, 512+9);
  593. tt_mem_op("all done", OP_EQ, expanded+512, 9);
  594. done:
  595. buf_free(buf);
  596. tor_compress_free(compress_state);
  597. tor_free(contents);
  598. tor_free(expanded);
  599. tor_free(msg);
  600. }
  601. static void
  602. test_buffers_compress(void *arg)
  603. {
  604. const char *methodname = arg;
  605. tt_assert(methodname);
  606. compress_method_t method = compression_method_get_by_name(methodname);
  607. tt_int_op(method, OP_NE, UNKNOWN_METHOD);
  608. if (! tor_compress_supports_method(method)) {
  609. tt_skip();
  610. }
  611. compression_level_t levels[] = {
  612. BEST_COMPRESSION,
  613. HIGH_COMPRESSION,
  614. MEDIUM_COMPRESSION,
  615. LOW_COMPRESSION
  616. };
  617. for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
  618. compression_level_t level = levels[l];
  619. test_buffers_compress_impl(method, level, 0);
  620. test_buffers_compress_impl(method, level, 1);
  621. test_buffers_compress_fin_at_chunk_end_impl(method, level);
  622. }
  623. done:
  624. ;
  625. }
  626. static const uint8_t *tls_read_ptr;
  627. static int n_remaining;
  628. static int next_reply_val[16];
  629. static int
  630. mock_tls_read(tor_tls_t *tls, char *cp, size_t len)
  631. {
  632. (void)tls;
  633. int rv = next_reply_val[0];
  634. if (rv > 0) {
  635. int max = rv > (int)len ? (int)len : rv;
  636. if (max > n_remaining)
  637. max = n_remaining;
  638. memcpy(cp, tls_read_ptr, max);
  639. rv = max;
  640. n_remaining -= max;
  641. tls_read_ptr += max;
  642. }
  643. memmove(next_reply_val, next_reply_val + 1, 15*sizeof(int));
  644. return rv;
  645. }
  646. static void
  647. test_buffers_tls_read_mocked(void *arg)
  648. {
  649. uint8_t *mem;
  650. buf_t *buf;
  651. (void)arg;
  652. mem = tor_malloc(64*1024);
  653. crypto_rand((char*)mem, 64*1024);
  654. tls_read_ptr = mem;
  655. n_remaining = 64*1024;
  656. MOCK(tor_tls_read, mock_tls_read);
  657. buf = buf_new();
  658. next_reply_val[0] = 1024;
  659. tt_int_op(128, OP_EQ, buf_read_from_tls(buf, NULL, 128));
  660. next_reply_val[0] = 5000;
  661. next_reply_val[1] = 5000;
  662. tt_int_op(6000, OP_EQ, buf_read_from_tls(buf, NULL, 6000));
  663. done:
  664. UNMOCK(tor_tls_read);
  665. tor_free(mem);
  666. buf_free(buf);
  667. }
  668. static void
  669. test_buffers_chunk_size(void *arg)
  670. {
  671. (void)arg;
  672. const int min = 256;
  673. const int max = 65536;
  674. tt_uint_op(preferred_chunk_size(3), OP_EQ, min);
  675. tt_uint_op(preferred_chunk_size(25), OP_EQ, min);
  676. tt_uint_op(preferred_chunk_size(0), OP_EQ, min);
  677. tt_uint_op(preferred_chunk_size(256), OP_EQ, 512);
  678. tt_uint_op(preferred_chunk_size(65400), OP_EQ, max);
  679. /* Here, we're implicitly saying that the chunk header overhead is
  680. * between 1 and 100 bytes. 24..48 would probably be more accurate. */
  681. tt_uint_op(preferred_chunk_size(65536), OP_GT, 65536);
  682. tt_uint_op(preferred_chunk_size(65536), OP_LT, 65536+100);
  683. tt_uint_op(preferred_chunk_size(165536), OP_GT, 165536);
  684. tt_uint_op(preferred_chunk_size(165536), OP_LT, 165536+100);
  685. done:
  686. ;
  687. }
  688. static void
  689. test_buffers_find_contentlen(void *arg)
  690. {
  691. static const struct {
  692. const char *headers;
  693. int r;
  694. int contentlen;
  695. } results[] = {
  696. { "Blah blah\r\nContent-Length: 1\r\n\r\n", 1, 1 },
  697. { "Blah blah\r\n\r\n", 0, 0 }, /* no content-len */
  698. { "Blah blah Content-Length: 1\r\n", 0, 0 }, /* no content-len. */
  699. { "Blah blah\r\nContent-Length: 100000\r\n", 1, 100000},
  700. { "Blah blah\r\nContent-Length: 1000000000000000000000000\r\n", -1, 0},
  701. { "Blah blah\r\nContent-Length: 0\r\n", 1, 0},
  702. { "Blah blah\r\nContent-Length: -1\r\n", -1, 0},
  703. { "Blah blah\r\nContent-Length: 1x\r\n", -1, 0},
  704. { "Blah blah\r\nContent-Length: 1 x\r\n", -1, 0},
  705. { "Blah blah\r\nContent-Length: 1 \r\n", 1, 1},
  706. { "Blah blah\r\nContent-Length: \r\n", -1, 0},
  707. { "Blah blah\r\nContent-Length: ", -1, 0},
  708. { "Blah blah\r\nContent-Length: 5050", -1, 0},
  709. { NULL, 0, 0 }
  710. };
  711. int i;
  712. (void)arg;
  713. for (i = 0; results[i].headers; ++i) {
  714. int r;
  715. size_t sz;
  716. size_t headerlen = strlen(results[i].headers);
  717. char * tmp = tor_memdup(results[i].headers, headerlen);/* ensure no eos */
  718. sz = 999; /* to ensure it gets set */
  719. r = buf_http_find_content_length(tmp, headerlen, &sz);
  720. tor_free(tmp);
  721. log_debug(LD_DIR, "%d: %s", i, escaped(results[i].headers));
  722. tt_int_op(r, OP_EQ, results[i].r);
  723. tt_int_op(sz, OP_EQ, results[i].contentlen);
  724. }
  725. done:
  726. ;
  727. }
  728. static void
  729. test_buffer_peek_startswith(void *arg)
  730. {
  731. (void)arg;
  732. buf_t *buf;
  733. buf = buf_new();
  734. tt_ptr_op(buf, OP_NE, NULL);
  735. tt_assert(buf_peek_startswith(buf, ""));
  736. tt_assert(! buf_peek_startswith(buf, "X"));
  737. buf_add(buf, "Tor", 3);
  738. tt_assert(buf_peek_startswith(buf, ""));
  739. tt_assert(buf_peek_startswith(buf, "T"));
  740. tt_assert(buf_peek_startswith(buf, "To"));
  741. tt_assert(buf_peek_startswith(buf, "Tor"));
  742. tt_assert(! buf_peek_startswith(buf, "Top"));
  743. tt_assert(! buf_peek_startswith(buf, "For"));
  744. tt_assert(! buf_peek_startswith(buf, "Tork"));
  745. tt_assert(! buf_peek_startswith(buf, "Torpor"));
  746. done:
  747. buf_free(buf);
  748. }
  749. struct testcase_t buffer_tests[] = {
  750. { "basic", test_buffers_basic, TT_FORK, NULL, NULL },
  751. { "copy", test_buffer_copy, TT_FORK, NULL, NULL },
  752. { "pullup", test_buffer_pullup, TT_FORK, NULL, NULL },
  753. { "startswith", test_buffer_peek_startswith, 0, NULL, NULL },
  754. { "ext_or_cmd", test_buffer_ext_or_cmd, TT_FORK, NULL, NULL },
  755. { "allocation_tracking", test_buffer_allocation_tracking, TT_FORK,
  756. NULL, NULL },
  757. { "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL },
  758. { "tls_read_mocked", test_buffers_tls_read_mocked, 0,
  759. NULL, NULL },
  760. { "chunk_size", test_buffers_chunk_size, 0, NULL, NULL },
  761. { "find_contentlen", test_buffers_find_contentlen, 0, NULL, NULL },
  762. { "compress/zlib", test_buffers_compress, TT_FORK,
  763. &passthrough_setup, (char*)"deflate" },
  764. { "compress/gzip", test_buffers_compress, TT_FORK,
  765. &passthrough_setup, (char*)"gzip" },
  766. { "compress/zstd", test_buffers_compress, TT_FORK,
  767. &passthrough_setup, (char*)"x-zstd" },
  768. { "compress/lzma", test_buffers_compress, TT_FORK,
  769. &passthrough_setup, (char*)"x-tor-lzma" },
  770. { "compress/none", test_buffers_compress, TT_FORK,
  771. &passthrough_setup, (char*)"identity" },
  772. END_OF_TESTCASES
  773. };