test_buffers.c 26 KB

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