test_evil.toml 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. # Tests for recovering from conditions which shouldn't normally
  2. # happen during normal operation of littlefs
  3. # invalid pointer tests (outside of block_count)
  4. [[case]] # invalid tail-pointer test
  5. define.TAIL_TYPE = ['LFS_TYPE_HARDTAIL', 'LFS_TYPE_SOFTTAIL']
  6. define.INVALSET = [0x3, 0x1, 0x2]
  7. in = "lfs.c"
  8. code = '''
  9. // create littlefs
  10. lfs_format(&lfs, &cfg) => 0;
  11. // change tail-pointer to invalid pointers
  12. lfs_init(&lfs, &cfg) => 0;
  13. lfs_mdir_t mdir;
  14. lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
  15. lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS(
  16. {LFS_MKTAG(LFS_TYPE_HARDTAIL, 0x3ff, 8),
  17. (lfs_block_t[2]){
  18. (INVALSET & 0x1) ? 0xcccccccc : 0,
  19. (INVALSET & 0x2) ? 0xcccccccc : 0}})) => 0;
  20. lfs_deinit(&lfs) => 0;
  21. // test that mount fails gracefully
  22. lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
  23. '''
  24. [[case]] # invalid dir pointer test
  25. define.INVALSET = [0x3, 0x1, 0x2]
  26. in = "lfs.c"
  27. code = '''
  28. // create littlefs
  29. lfs_format(&lfs, &cfg) => 0;
  30. // make a dir
  31. lfs_mount(&lfs, &cfg) => 0;
  32. lfs_mkdir(&lfs, "dir_here") => 0;
  33. lfs_unmount(&lfs) => 0;
  34. // change the dir pointer to be invalid
  35. lfs_init(&lfs, &cfg) => 0;
  36. lfs_mdir_t mdir;
  37. lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
  38. // make sure id 1 == our directory
  39. lfs_dir_get(&lfs, &mdir,
  40. LFS_MKTAG(0x700, 0x3ff, 0),
  41. LFS_MKTAG(LFS_TYPE_NAME, 1, strlen("dir_here")), buffer)
  42. => LFS_MKTAG(LFS_TYPE_DIR, 1, strlen("dir_here"));
  43. assert(memcmp((char*)buffer, "dir_here", strlen("dir_here")) == 0);
  44. // change dir pointer
  45. lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS(
  46. {LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 1, 8),
  47. (lfs_block_t[2]){
  48. (INVALSET & 0x1) ? 0xcccccccc : 0,
  49. (INVALSET & 0x2) ? 0xcccccccc : 0}})) => 0;
  50. lfs_deinit(&lfs) => 0;
  51. // test that accessing our bad dir fails, note there's a number
  52. // of ways to access the dir, some can fail, but some don't
  53. lfs_mount(&lfs, &cfg) => 0;
  54. lfs_stat(&lfs, "dir_here", &info) => 0;
  55. assert(strcmp(info.name, "dir_here") == 0);
  56. assert(info.type == LFS_TYPE_DIR);
  57. lfs_dir_open(&lfs, &dir, "dir_here") => LFS_ERR_CORRUPT;
  58. lfs_stat(&lfs, "dir_here/file_here", &info) => LFS_ERR_CORRUPT;
  59. lfs_dir_open(&lfs, &dir, "dir_here/dir_here") => LFS_ERR_CORRUPT;
  60. lfs_file_open(&lfs, &file, "dir_here/file_here",
  61. LFS_O_RDONLY) => LFS_ERR_CORRUPT;
  62. lfs_file_open(&lfs, &file, "dir_here/file_here",
  63. LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_CORRUPT;
  64. lfs_unmount(&lfs) => 0;
  65. '''
  66. [[case]] # invalid file pointer test
  67. in = "lfs.c"
  68. define.SIZE = [10, 1000, 100000] # faked file size
  69. code = '''
  70. // create littlefs
  71. lfs_format(&lfs, &cfg) => 0;
  72. // make a file
  73. lfs_mount(&lfs, &cfg) => 0;
  74. lfs_file_open(&lfs, &file, "file_here",
  75. LFS_O_WRONLY | LFS_O_CREAT) => 0;
  76. lfs_file_close(&lfs, &file) => 0;
  77. lfs_unmount(&lfs) => 0;
  78. // change the file pointer to be invalid
  79. lfs_init(&lfs, &cfg) => 0;
  80. lfs_mdir_t mdir;
  81. lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
  82. // make sure id 1 == our file
  83. lfs_dir_get(&lfs, &mdir,
  84. LFS_MKTAG(0x700, 0x3ff, 0),
  85. LFS_MKTAG(LFS_TYPE_NAME, 1, strlen("file_here")), buffer)
  86. => LFS_MKTAG(LFS_TYPE_REG, 1, strlen("file_here"));
  87. assert(memcmp((char*)buffer, "file_here", strlen("file_here")) == 0);
  88. // change file pointer
  89. lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS(
  90. {LFS_MKTAG(LFS_TYPE_CTZSTRUCT, 1, sizeof(struct lfs_ctz)),
  91. &(struct lfs_ctz){0xcccccccc, lfs_tole32(SIZE)}})) => 0;
  92. lfs_deinit(&lfs) => 0;
  93. // test that accessing our bad file fails, note there's a number
  94. // of ways to access the dir, some can fail, but some don't
  95. lfs_mount(&lfs, &cfg) => 0;
  96. lfs_stat(&lfs, "file_here", &info) => 0;
  97. assert(strcmp(info.name, "file_here") == 0);
  98. assert(info.type == LFS_TYPE_REG);
  99. assert(info.size == SIZE);
  100. lfs_file_open(&lfs, &file, "file_here", LFS_O_RDONLY) => 0;
  101. lfs_file_read(&lfs, &file, buffer, SIZE) => LFS_ERR_CORRUPT;
  102. lfs_file_close(&lfs, &file) => 0;
  103. // any allocs that traverse CTZ must unfortunately must fail
  104. if (SIZE > 2*LFS_BLOCK_SIZE) {
  105. lfs_mkdir(&lfs, "dir_here") => LFS_ERR_CORRUPT;
  106. }
  107. lfs_unmount(&lfs) => 0;
  108. '''
  109. [[case]] # invalid pointer in CTZ skip-list test
  110. define.SIZE = ['2*LFS_BLOCK_SIZE', '3*LFS_BLOCK_SIZE', '4*LFS_BLOCK_SIZE']
  111. in = "lfs.c"
  112. code = '''
  113. // create littlefs
  114. lfs_format(&lfs, &cfg) => 0;
  115. // make a file
  116. lfs_mount(&lfs, &cfg) => 0;
  117. lfs_file_open(&lfs, &file, "file_here",
  118. LFS_O_WRONLY | LFS_O_CREAT) => 0;
  119. for (int i = 0; i < SIZE; i++) {
  120. char c = 'c';
  121. lfs_file_write(&lfs, &file, &c, 1) => 1;
  122. }
  123. lfs_file_close(&lfs, &file) => 0;
  124. lfs_unmount(&lfs) => 0;
  125. // change pointer in CTZ skip-list to be invalid
  126. lfs_init(&lfs, &cfg) => 0;
  127. lfs_mdir_t mdir;
  128. lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
  129. // make sure id 1 == our file and get our CTZ structure
  130. lfs_dir_get(&lfs, &mdir,
  131. LFS_MKTAG(0x700, 0x3ff, 0),
  132. LFS_MKTAG(LFS_TYPE_NAME, 1, strlen("file_here")), buffer)
  133. => LFS_MKTAG(LFS_TYPE_REG, 1, strlen("file_here"));
  134. assert(memcmp((char*)buffer, "file_here", strlen("file_here")) == 0);
  135. struct lfs_ctz ctz;
  136. lfs_dir_get(&lfs, &mdir,
  137. LFS_MKTAG(0x700, 0x3ff, 0),
  138. LFS_MKTAG(LFS_TYPE_STRUCT, 1, sizeof(struct lfs_ctz)), &ctz)
  139. => LFS_MKTAG(LFS_TYPE_CTZSTRUCT, 1, sizeof(struct lfs_ctz));
  140. lfs_ctz_fromle32(&ctz);
  141. // rewrite block to contain bad pointer
  142. uint8_t bbuffer[LFS_BLOCK_SIZE];
  143. cfg.read(&cfg, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
  144. uint32_t bad = lfs_tole32(0xcccccccc);
  145. memcpy(&bbuffer[0], &bad, sizeof(bad));
  146. memcpy(&bbuffer[4], &bad, sizeof(bad));
  147. cfg.erase(&cfg, ctz.head) => 0;
  148. cfg.prog(&cfg, ctz.head, 0, bbuffer, LFS_BLOCK_SIZE) => 0;
  149. lfs_deinit(&lfs) => 0;
  150. // test that accessing our bad file fails, note there's a number
  151. // of ways to access the dir, some can fail, but some don't
  152. lfs_mount(&lfs, &cfg) => 0;
  153. lfs_stat(&lfs, "file_here", &info) => 0;
  154. assert(strcmp(info.name, "file_here") == 0);
  155. assert(info.type == LFS_TYPE_REG);
  156. assert(info.size == SIZE);
  157. lfs_file_open(&lfs, &file, "file_here", LFS_O_RDONLY) => 0;
  158. lfs_file_read(&lfs, &file, buffer, SIZE) => LFS_ERR_CORRUPT;
  159. lfs_file_close(&lfs, &file) => 0;
  160. // any allocs that traverse CTZ must unfortunately must fail
  161. if (SIZE > 2*LFS_BLOCK_SIZE) {
  162. lfs_mkdir(&lfs, "dir_here") => LFS_ERR_CORRUPT;
  163. }
  164. lfs_unmount(&lfs) => 0;
  165. '''
  166. [[case]] # invalid gstate pointer
  167. define.INVALSET = [0x3, 0x1, 0x2]
  168. in = "lfs.c"
  169. code = '''
  170. // create littlefs
  171. lfs_format(&lfs, &cfg) => 0;
  172. // create an invalid gstate
  173. lfs_init(&lfs, &cfg) => 0;
  174. lfs_mdir_t mdir;
  175. lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
  176. lfs_fs_prepmove(&lfs, 1, (lfs_block_t [2]){
  177. (INVALSET & 0x1) ? 0xcccccccc : 0,
  178. (INVALSET & 0x2) ? 0xcccccccc : 0});
  179. lfs_dir_commit(&lfs, &mdir, NULL, 0) => 0;
  180. lfs_deinit(&lfs) => 0;
  181. // test that mount fails gracefully
  182. // mount may not fail, but our first alloc should fail when
  183. // we try to fix the gstate
  184. lfs_mount(&lfs, &cfg) => 0;
  185. lfs_mkdir(&lfs, "should_fail") => LFS_ERR_CORRUPT;
  186. lfs_unmount(&lfs) => 0;
  187. '''
  188. # cycle detection/recovery tests
  189. [[case]] # metadata-pair threaded-list loop test
  190. in = "lfs.c"
  191. code = '''
  192. // create littlefs
  193. lfs_format(&lfs, &cfg) => 0;
  194. // change tail-pointer to point to ourself
  195. lfs_init(&lfs, &cfg) => 0;
  196. lfs_mdir_t mdir;
  197. lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
  198. lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS(
  199. {LFS_MKTAG(LFS_TYPE_HARDTAIL, 0x3ff, 8),
  200. (lfs_block_t[2]){0, 1}})) => 0;
  201. lfs_deinit(&lfs) => 0;
  202. // test that mount fails gracefully
  203. lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
  204. '''
  205. [[case]] # metadata-pair threaded-list 2-length loop test
  206. in = "lfs.c"
  207. code = '''
  208. // create littlefs with child dir
  209. lfs_format(&lfs, &cfg) => 0;
  210. lfs_mount(&lfs, &cfg) => 0;
  211. lfs_mkdir(&lfs, "child") => 0;
  212. lfs_unmount(&lfs) => 0;
  213. // find child
  214. lfs_init(&lfs, &cfg) => 0;
  215. lfs_mdir_t mdir;
  216. lfs_block_t pair[2];
  217. lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
  218. lfs_dir_get(&lfs, &mdir,
  219. LFS_MKTAG(0x7ff, 0x3ff, 0),
  220. LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 1, sizeof(pair)), pair)
  221. => LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 1, sizeof(pair));
  222. lfs_pair_fromle32(pair);
  223. // change tail-pointer to point to root
  224. lfs_dir_fetch(&lfs, &mdir, pair) => 0;
  225. lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS(
  226. {LFS_MKTAG(LFS_TYPE_HARDTAIL, 0x3ff, 8),
  227. (lfs_block_t[2]){0, 1}})) => 0;
  228. lfs_deinit(&lfs) => 0;
  229. // test that mount fails gracefully
  230. lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
  231. '''
  232. [[case]] # metadata-pair threaded-list 1-length child loop test
  233. in = "lfs.c"
  234. code = '''
  235. // create littlefs with child dir
  236. lfs_format(&lfs, &cfg) => 0;
  237. lfs_mount(&lfs, &cfg) => 0;
  238. lfs_mkdir(&lfs, "child") => 0;
  239. lfs_unmount(&lfs) => 0;
  240. // find child
  241. lfs_init(&lfs, &cfg) => 0;
  242. lfs_mdir_t mdir;
  243. lfs_block_t pair[2];
  244. lfs_dir_fetch(&lfs, &mdir, (lfs_block_t[2]){0, 1}) => 0;
  245. lfs_dir_get(&lfs, &mdir,
  246. LFS_MKTAG(0x7ff, 0x3ff, 0),
  247. LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 1, sizeof(pair)), pair)
  248. => LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 1, sizeof(pair));
  249. lfs_pair_fromle32(pair);
  250. // change tail-pointer to point to ourself
  251. lfs_dir_fetch(&lfs, &mdir, pair) => 0;
  252. lfs_dir_commit(&lfs, &mdir, LFS_MKATTRS(
  253. {LFS_MKTAG(LFS_TYPE_HARDTAIL, 0x3ff, 8), pair})) => 0;
  254. lfs_deinit(&lfs) => 0;
  255. // test that mount fails gracefully
  256. lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
  257. '''