A clone of btpd with my configuration changes.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

346 lines
6.2 KiB

  1. #include <assert.h>
  2. #include <ctype.h>
  3. #include <errno.h>
  4. #include <inttypes.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "benc.h"
  8. #define benc_safeset(out, val) if ((out) != NULL) *(out) = (val)
  9. static const char *benc_validate_aux(const char *p, const char *end);
  10. int
  11. benc_validate(const char *p, size_t len)
  12. {
  13. const char *end = p + len - 1;
  14. if (len <= 0)
  15. return EINVAL;
  16. return benc_validate_aux(p, end) == end ? 0 : EINVAL;
  17. }
  18. static const char *
  19. benc_validate_aux(const char *p, const char *end)
  20. {
  21. size_t d = 0;
  22. switch (*p) {
  23. case 'd':
  24. d = 1;
  25. case 'l':
  26. for (p++; p <= end && *p != 'e'; p++) {
  27. if (d != 0) {
  28. if (d % 2 == 1 && !isdigit(*p))
  29. return NULL;
  30. else
  31. d++;
  32. }
  33. if ((p = benc_validate_aux(p, end)) == NULL)
  34. return NULL;
  35. }
  36. if (p > end || (d != 0 && d % 2 != 1))
  37. return NULL;
  38. break;
  39. case 'i':
  40. p++;
  41. if (p > end)
  42. return NULL;
  43. if (*p == '-')
  44. p++;
  45. if (p > end || !isdigit(*p))
  46. return NULL;
  47. p++;
  48. while (p <= end && isdigit(*p))
  49. p++;
  50. if (p > end || *p != 'e')
  51. return NULL;
  52. break;
  53. default:
  54. if (isdigit(*p)) {
  55. size_t len = 0;
  56. while (p <= end && isdigit(*p)) {
  57. len *= 10;
  58. len += *p - '0';
  59. p++;
  60. }
  61. if (p <= end && *p == ':' && p + len <= end)
  62. p += len;
  63. else
  64. return NULL;
  65. }
  66. else
  67. return NULL;
  68. break;
  69. }
  70. return p;
  71. }
  72. size_t
  73. benc_length(const char *p)
  74. {
  75. size_t blen;
  76. const char *next;
  77. switch (*p) {
  78. case 'd':
  79. case 'l':
  80. blen = 2; // [l|d]...e
  81. next = benc_first(p);
  82. while (*next != 'e') {
  83. size_t len = benc_length(next);
  84. blen += len;
  85. next += len;
  86. }
  87. return blen;
  88. case 'i':
  89. for (next = p + 1; *next != 'e'; next++)
  90. ;
  91. return next - p + 1;
  92. default:
  93. assert(benc_str(p, &next, &blen, NULL) == 0);
  94. return next - p + blen;
  95. }
  96. }
  97. size_t
  98. benc_nelems(const char *p)
  99. {
  100. size_t nelems = 0;
  101. for (p = benc_first(p); p != NULL; p = benc_next(p))
  102. nelems++;
  103. return nelems;
  104. }
  105. const char *
  106. benc_first(const char *p)
  107. {
  108. assert(benc_islst(p));
  109. return *(p + 1) == 'e' ? NULL : p + 1;
  110. }
  111. const char *
  112. benc_next(const char *p)
  113. {
  114. size_t blen = benc_length(p);
  115. return *(p + blen) == 'e' ? NULL : p + blen;
  116. }
  117. int
  118. benc_str(const char *p, const char **out, size_t *len, const char**next)
  119. {
  120. size_t blen = 0;
  121. assert(isdigit(*p));
  122. blen = *p - '0';
  123. p++;
  124. while (isdigit(*p)) {
  125. blen *= 10;
  126. blen += *p - '0';
  127. p++;
  128. }
  129. assert(*p == ':');
  130. benc_safeset(len, blen);
  131. benc_safeset(out, p + 1);
  132. benc_safeset(next, *(p + blen + 1) == 'e' ? NULL : p + blen + 1);
  133. return 0;
  134. }
  135. int
  136. benc_strz(const char *p, char **out, size_t *len, const char **next)
  137. {
  138. int err;
  139. size_t blen;
  140. const char *bstr;
  141. if ((err = benc_str(p, &bstr, &blen, next)) == 0) {
  142. if ((*out = malloc(blen + 1)) != NULL) {
  143. memcpy(*out, bstr, blen);
  144. (*out)[blen] = '\0';
  145. benc_safeset(len, blen);
  146. } else
  147. err = ENOMEM;
  148. }
  149. return err;
  150. }
  151. int
  152. benc_stra(const char *p, char **out, size_t *len, const char **next)
  153. {
  154. int err;
  155. size_t blen;
  156. const char *bstr;
  157. if ((err = benc_str(p, &bstr, &blen, next)) == 0) {
  158. if ((*out = malloc(blen)) != NULL) {
  159. memcpy(*out, bstr, blen);
  160. benc_safeset(len, blen);
  161. } else
  162. err = ENOMEM;
  163. }
  164. return err;
  165. }
  166. int
  167. benc_int64(const char *p, int64_t *out, const char **next)
  168. {
  169. int sign = 1;
  170. int64_t res = 0;
  171. assert(*p == 'i');
  172. p++;
  173. if (*p == '-') {
  174. sign = -1;
  175. p++;
  176. }
  177. assert(isdigit(*p));
  178. res += sign * (*p - '0');
  179. p++;
  180. while (isdigit(*p)) {
  181. res *= sign * 10;
  182. res += sign * (*p - '0');
  183. p++;
  184. }
  185. assert(*p == 'e');
  186. benc_safeset(out, res);
  187. benc_safeset(next, *(p + 1) == 'e' ? NULL : p + 1);
  188. return 0;
  189. }
  190. int
  191. benc_uint32(const char *p, uint32_t *out, const char **next)
  192. {
  193. int err;
  194. int64_t res;
  195. if ((err = benc_int64(p, &res, next)) == 0) {
  196. if (res >= 0 && res <= 0xffffffffUL)
  197. *out = (uint32_t)res;
  198. else
  199. err = EINVAL;
  200. }
  201. return err;
  202. }
  203. int
  204. benc_dget_any(const char *p, const char *key, const char **val)
  205. {
  206. int res;
  207. size_t len, blen;
  208. const char *bstr;
  209. assert(benc_isdct(p));
  210. len = strlen(key);
  211. p = benc_first(p);
  212. while (p != NULL) {
  213. if ((res = benc_str(p, &bstr, &blen, &p)) != 0)
  214. return res;
  215. res = strncmp(bstr, key, blen);
  216. if (res == 0 && len == blen) {
  217. *val = p;
  218. return 0;
  219. } else if (res <= 0) {
  220. p = benc_next(p);
  221. } else
  222. return ENOENT;
  223. }
  224. return ENOENT;
  225. }
  226. int
  227. benc_dget_lst(const char *p, const char *key, const char **val)
  228. {
  229. int err;
  230. if ((err = benc_dget_any(p, key, val)) == 0)
  231. if (!benc_islst(*val))
  232. err = EINVAL;
  233. return err;
  234. }
  235. int
  236. benc_dget_dct(const char *p, const char *key, const char **val)
  237. {
  238. int err;
  239. if ((err = benc_dget_any(p, key, val)) == 0)
  240. if (!benc_isdct(*val))
  241. err = EINVAL;
  242. return err;
  243. }
  244. int
  245. benc_dget_str(const char *p, const char *key, const char **val, size_t *len)
  246. {
  247. int err;
  248. const char *sp;
  249. if ((err = benc_dget_any(p, key, &sp)) == 0)
  250. err = benc_isstr(sp) ? benc_str(sp, val, len, NULL) : EINVAL;
  251. return err;
  252. }
  253. int
  254. benc_dget_stra(const char *p, const char *key, char **val, size_t *len)
  255. {
  256. int err;
  257. const char *sp;
  258. if ((err = benc_dget_any(p, key, &sp)) == 0)
  259. err = benc_isstr(sp) ? benc_stra(sp, val, len, NULL) : EINVAL;
  260. return err;
  261. }
  262. int
  263. benc_dget_strz(const char *p, const char *key, char **val, size_t *len)
  264. {
  265. int err;
  266. const char *sp;
  267. if ((err = benc_dget_any(p, key, &sp)) == 0)
  268. err = benc_isstr(sp) ? benc_strz(sp, val, len, NULL) : EINVAL;
  269. return err;
  270. }
  271. int
  272. benc_dget_int64(const char *p, const char *key, int64_t *val)
  273. {
  274. int err;
  275. const char *ip;
  276. if ((err = benc_dget_any(p, key, &ip)) == 0)
  277. err = benc_isint(ip) ? benc_int64(ip, val, NULL) : EINVAL;
  278. return err;
  279. }
  280. int
  281. benc_dget_uint32(const char *p, const char *key, uint32_t *val)
  282. {
  283. int err;
  284. const char *ip;
  285. if ((err = benc_dget_any(p, key, &ip)) == 0)
  286. err = benc_isint(ip) ? benc_uint32(ip, val, NULL) : EINVAL;
  287. return err;
  288. }
  289. int
  290. benc_islst(const char *p)
  291. {
  292. return *p == 'l' || *p == 'd';
  293. }
  294. int
  295. benc_isdct(const char *p)
  296. {
  297. return *p == 'd';
  298. }
  299. int
  300. benc_isint(const char *p)
  301. {
  302. return *p == 'i';
  303. }
  304. int
  305. benc_isstr(const char *p)
  306. {
  307. return isdigit(*p);
  308. }