gvariant-util.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380
  1. /*
  2. *
  3. * Embedded Linux library
  4. *
  5. * Copyright (C) 2011-2014 Intel Corporation. All rights reserved.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #define _GNU_SOURCE
  26. #include <stdbool.h>
  27. #include <unistd.h>
  28. #include <string.h>
  29. #include <endian.h>
  30. #include <limits.h>
  31. #include "private.h"
  32. #include "useful.h"
  33. #include "util.h"
  34. #include "queue.h"
  35. #include "string.h"
  36. #include "log.h"
  37. #include "dbus.h"
  38. #include "dbus-private.h"
  39. #include "gvariant-private.h"
  40. static const char *simple_types = "sogybnqiuxtdh";
  41. static const char *variable_types = "sogav";
  42. static const char *fixed_types = "bynqhiuxtd";
  43. /*
  44. * The alignment of a container type is equal to the largest alignment of
  45. * any potential child of that container. This means that, even if an array
  46. * of 32-bit integers is empty, it still must be aligned to the nearest
  47. * multiple of 4 bytes. It also means that the variant type (described below)
  48. * has an alignment of 8 (since it could potentially contain a value of any
  49. * other type and the maximum alignment is 8).
  50. */
  51. static int get_basic_alignment(const char type)
  52. {
  53. switch (type) {
  54. case 'b':
  55. return 1;
  56. case 'y':
  57. return 1;
  58. case 'n':
  59. case 'q':
  60. return 2;
  61. case 'i':
  62. case 'u':
  63. return 4;
  64. case 'x':
  65. case 't':
  66. case 'd':
  67. return 8;
  68. case 's':
  69. case 'g':
  70. case 'o':
  71. return 1;
  72. case 'h':
  73. return 4;
  74. case 'v':
  75. return 8;
  76. default:
  77. return 0;
  78. }
  79. }
  80. static int get_basic_fixed_size(const char type)
  81. {
  82. switch (type) {
  83. case 'b':
  84. return 1;
  85. case 'y':
  86. return 1;
  87. case 'n':
  88. case 'q':
  89. return 2;
  90. case 'i':
  91. case 'u':
  92. return 4;
  93. case 'x':
  94. case 't':
  95. case 'd':
  96. return 8;
  97. case 'h':
  98. return 4;
  99. default:
  100. return 0;
  101. }
  102. }
  103. static const char *validate_next_type(const char *sig, int *out_alignment)
  104. {
  105. char s = *sig;
  106. int alignment;
  107. if (s == '\0')
  108. return NULL;
  109. if (strchr(simple_types, s) || s == 'v') {
  110. *out_alignment = get_basic_alignment(s);
  111. return sig + 1;
  112. }
  113. switch (s) {
  114. case 'a':
  115. return validate_next_type(++sig, out_alignment);
  116. case '{':
  117. s = *++sig;
  118. /* Dictionary keys can only be simple types */
  119. if (!strchr(simple_types, s))
  120. return NULL;
  121. alignment = get_basic_alignment(s);
  122. sig = validate_next_type(sig + 1, out_alignment);
  123. if (!sig)
  124. return NULL;
  125. if (*sig != '}')
  126. return NULL;
  127. if (alignment > *out_alignment)
  128. *out_alignment = alignment;
  129. return sig + 1;
  130. case '(':
  131. {
  132. int max_alignment = 1, alignment;
  133. sig++;
  134. while (sig && *sig != ')') {
  135. sig = validate_next_type(sig, &alignment);
  136. if (alignment > max_alignment)
  137. max_alignment = alignment;
  138. }
  139. if (!sig)
  140. return NULL;
  141. if (*sig != ')')
  142. return NULL;
  143. *out_alignment = max_alignment;
  144. return sig + 1;
  145. }
  146. }
  147. return NULL;
  148. }
  149. bool _gvariant_valid_signature(const char *sig)
  150. {
  151. const char *s = sig;
  152. int a;
  153. if (strlen(sig) > 255)
  154. return false;
  155. do {
  156. s = validate_next_type(s, &a);
  157. if (!s)
  158. return false;
  159. } while (*s);
  160. return true;
  161. }
  162. int _gvariant_num_children(const char *sig)
  163. {
  164. const char *s = sig;
  165. int a;
  166. int num_children = 0;
  167. if (strlen(sig) > 255)
  168. return false;
  169. do {
  170. s = validate_next_type(s, &a);
  171. if (!s)
  172. return -1;
  173. num_children += 1;
  174. } while (*s);
  175. return num_children;
  176. }
  177. int _gvariant_get_alignment(const char *sig)
  178. {
  179. int max_alignment = 1, alignment;
  180. const char *s = sig;
  181. /* 8 is the largest alignment possible, so quit if we reach it */
  182. while (*s && max_alignment != 8) {
  183. s = validate_next_type(s, &alignment);
  184. if (!s)
  185. return 0;
  186. if (alignment > max_alignment)
  187. max_alignment = alignment;
  188. }
  189. return max_alignment;
  190. }
  191. bool _gvariant_is_fixed_size(const char *sig)
  192. {
  193. while (*sig != 0) {
  194. if (strchr(variable_types, sig[0]))
  195. return false;
  196. sig += 1;
  197. }
  198. return true;
  199. }
  200. int _gvariant_get_fixed_size(const char *sig)
  201. {
  202. const char *s = sig;
  203. const char *p;
  204. int size = 0;
  205. int alignment;
  206. int max_alignment = 1;
  207. int r;
  208. while (*s) {
  209. if (strchr(variable_types, *s))
  210. return 0;
  211. if (strchr(fixed_types, *s)) {
  212. alignment = get_basic_alignment(*s);
  213. if (alignment > max_alignment)
  214. max_alignment = alignment;
  215. size = align_len(size, alignment);
  216. size += get_basic_fixed_size(*s);
  217. s++;
  218. continue;
  219. }
  220. if (*s == '}' || *s == ')')
  221. break;
  222. p = validate_next_type(s, &alignment);
  223. if (!p)
  224. return 0;
  225. if (alignment > max_alignment)
  226. max_alignment = alignment;
  227. size = align_len(size, alignment);
  228. /* Handle special case of unit type */
  229. if (s[0] == '(' && s[1] == ')')
  230. r = 1;
  231. else
  232. r = _gvariant_get_fixed_size(s + 1);
  233. if (r == 0)
  234. return 0;
  235. size += r;
  236. s = p;
  237. }
  238. size = align_len(size, max_alignment);
  239. return size;
  240. }
  241. static inline size_t offset_length(size_t size, size_t n_offsets)
  242. {
  243. if (size + n_offsets <= 0xff)
  244. return 1;
  245. if (size + n_offsets * 2 <= 0xffff)
  246. return 2;
  247. if (size + n_offsets * 4 <= 0xffffffff)
  248. return 4;
  249. return 8;
  250. }
  251. static inline size_t read_word_le(const void *p, size_t sz) {
  252. union {
  253. uint16_t u16;
  254. uint32_t u32;
  255. uint64_t u64;
  256. } x;
  257. if (sz == 1)
  258. return *(uint8_t *) p;
  259. memcpy(&x, p, sz);
  260. if (sz == 2)
  261. return le16toh(x.u16);
  262. if (sz == 4)
  263. return le32toh(x.u32);
  264. return le64toh(x.u64);
  265. }
  266. static inline void write_word_le(void *p, size_t value, size_t sz) {
  267. union {
  268. uint16_t u16;
  269. uint32_t u32;
  270. uint64_t u64;
  271. } x;
  272. if (sz == 1) {
  273. *(uint8_t *) p = value;
  274. return;
  275. }
  276. if (sz == 2)
  277. x.u16 = htole16((uint16_t) value);
  278. else if (sz == 4)
  279. x.u32 = htole32((uint32_t) value);
  280. else
  281. x.u64 = htole64((uint64_t) value);
  282. memcpy(p, &x, sz);
  283. }
  284. static bool gvariant_iter_init_internal(struct l_dbus_message_iter *iter,
  285. struct l_dbus_message *message,
  286. enum dbus_container_type type,
  287. const char *sig_start,
  288. const char *sig_end, const void *data,
  289. size_t len)
  290. {
  291. const char *p;
  292. int i;
  293. int v;
  294. char subsig[256];
  295. unsigned int num_variable = 0;
  296. unsigned int offset_len = offset_length(len, 0);
  297. size_t last_offset;
  298. struct gvariant_type_info {
  299. uint8_t sig_start;
  300. uint8_t sig_end;
  301. bool fixed_size : 1;
  302. unsigned int alignment : 4;
  303. size_t end; /* Index past the end of the type */
  304. } *children;
  305. int n_children;
  306. if (sig_end) {
  307. size_t len = sig_end - sig_start;
  308. memcpy(subsig, sig_start, len);
  309. subsig[len] = '\0';
  310. } else
  311. strcpy(subsig, sig_start);
  312. iter->message = message;
  313. iter->sig_start = sig_start;
  314. iter->sig_len = strlen(subsig);
  315. iter->sig_pos = 0;
  316. iter->data = data;
  317. iter->len = len;
  318. iter->pos = 0;
  319. if (subsig[0] != '\0') {
  320. n_children = _gvariant_num_children(subsig);
  321. if (n_children < 0)
  322. return false;
  323. children = l_new(struct gvariant_type_info, n_children);
  324. } else {
  325. n_children = 0;
  326. children = NULL;
  327. }
  328. for (p = sig_start, i = 0; i < n_children; i++) {
  329. int alignment;
  330. size_t size;
  331. size_t len;
  332. children[i].sig_start = p - sig_start;
  333. p = validate_next_type(p, &alignment);
  334. children[i].sig_end = p - sig_start;
  335. len = children[i].sig_end - children[i].sig_start;
  336. memcpy(subsig, sig_start + children[i].sig_start, len);
  337. subsig[len] = '\0';
  338. children[i].alignment = alignment;
  339. children[i].fixed_size = _gvariant_is_fixed_size(subsig);
  340. if (children[i].fixed_size) {
  341. size = _gvariant_get_fixed_size(subsig);
  342. children[i].end = size;
  343. } else if (i + 1 < n_children)
  344. num_variable += 1;
  345. }
  346. if (len < num_variable * offset_len)
  347. goto fail;
  348. last_offset = len - num_variable * offset_len;
  349. if (num_variable > 0)
  350. iter->offsets = iter->data + len - offset_len;
  351. else
  352. iter->offsets = NULL;
  353. for (i = 0, v = 0; i < n_children; i++) {
  354. size_t o;
  355. if (children[i].fixed_size) {
  356. if (i == 0)
  357. continue;
  358. o = align_len(children[i-1].end,
  359. children[i].alignment);
  360. children[i].end += o;
  361. if (children[i].end > len)
  362. goto fail;
  363. continue;
  364. }
  365. if (num_variable == 0) {
  366. children[i].end = last_offset;
  367. continue;
  368. }
  369. v += 1;
  370. children[i].end = read_word_le(data + len - offset_len * v,
  371. offset_len);
  372. num_variable -= 1;
  373. if (children[i].end > len)
  374. goto fail;
  375. }
  376. iter->container_type = type;
  377. if (type == DBUS_CONTAINER_TYPE_ARRAY &&
  378. !children[0].fixed_size) {
  379. size_t offset = read_word_le(iter->data + iter->len -
  380. offset_len, offset_len);
  381. iter->offsets = iter->data + offset;
  382. }
  383. l_free(children);
  384. return true;
  385. fail:
  386. l_free(children);
  387. return false;
  388. }
  389. bool _gvariant_iter_init(struct l_dbus_message_iter *iter,
  390. struct l_dbus_message *message,
  391. const char *sig_start, const char *sig_end,
  392. const void *data, size_t len)
  393. {
  394. return gvariant_iter_init_internal(iter, message,
  395. DBUS_CONTAINER_TYPE_STRUCT,
  396. sig_start, sig_end, data, len);
  397. }
  398. static const void *next_item(struct l_dbus_message_iter *iter,
  399. size_t *out_item_size)
  400. {
  401. const void *start;
  402. const char *p;
  403. char sig[256];
  404. int alignment;
  405. bool fixed_size;
  406. bool last_member;
  407. unsigned int sig_len;
  408. unsigned int offset_len;
  409. memcpy(sig, iter->sig_start + iter->sig_pos,
  410. iter->sig_len - iter->sig_pos);
  411. sig[iter->sig_len - iter->sig_pos] = '\0';
  412. /*
  413. * Find the next type and make a note whether it is the last in the
  414. * structure. Arrays will always have a single complete type, so
  415. * last_member will always be true.
  416. */
  417. p = validate_next_type(sig, &alignment);
  418. if (!p)
  419. return NULL;
  420. sig_len = p - sig;
  421. last_member = *p == '\0';
  422. sig[sig_len] = '\0';
  423. fixed_size = _gvariant_is_fixed_size(sig);
  424. if (iter->container_type != DBUS_CONTAINER_TYPE_ARRAY)
  425. iter->sig_pos += sig_len;
  426. iter->pos = align_len(iter->pos, alignment);
  427. if (fixed_size) {
  428. *out_item_size = _gvariant_get_fixed_size(sig);
  429. goto done;
  430. }
  431. if (iter->container_type != DBUS_CONTAINER_TYPE_ARRAY && last_member) {
  432. unsigned int len = iter->len;
  433. offset_len = offset_length(iter->len, 0);
  434. if (iter->offsets && iter->offsets + offset_len <
  435. iter->data + len)
  436. len = iter->offsets + offset_len - iter->data;
  437. *out_item_size = len - iter->pos;
  438. goto done;
  439. }
  440. if (iter->offsets >= iter->data + iter->len)
  441. return NULL;
  442. offset_len = offset_length(iter->len, 0);
  443. *out_item_size = read_word_le(iter->offsets, offset_len) - iter->pos;
  444. /* In structures the offsets are in reverse order */
  445. if (iter->container_type == DBUS_CONTAINER_TYPE_ARRAY)
  446. iter->offsets += offset_len;
  447. else
  448. iter->offsets -= offset_len;
  449. done:
  450. start = iter->data + iter->pos;
  451. if (start >= iter->data + iter->len)
  452. return NULL;
  453. iter->pos += *out_item_size;
  454. return start;
  455. }
  456. bool _gvariant_iter_next_entry_basic(struct l_dbus_message_iter *iter,
  457. char type, void *out)
  458. {
  459. size_t item_size = 0;
  460. const void *start;
  461. uint8_t uint8_val;
  462. uint16_t uint16_val;
  463. uint32_t uint32_val;
  464. uint64_t uint64_val;
  465. int16_t int16_val;
  466. int32_t int32_val;
  467. int64_t int64_val;
  468. if (iter->pos >= iter->len)
  469. return false;
  470. if (iter->sig_start[iter->sig_pos] != type)
  471. return false;
  472. start = next_item(iter, &item_size);
  473. if (!start)
  474. return false;
  475. switch (type) {
  476. case 'o':
  477. case 's':
  478. case 'g':
  479. {
  480. const void *end = memchr(start, 0, item_size);
  481. if (!end)
  482. return false;
  483. *(const char**) out = start;
  484. break;
  485. }
  486. case 'b':
  487. uint8_val = l_get_u8(start);
  488. *(bool *) out = !!uint8_val;
  489. break;
  490. case 'y':
  491. uint8_val = l_get_u8(start);
  492. *(uint8_t *) out = uint8_val;
  493. break;
  494. case 'n':
  495. int16_val = l_get_s16(start);
  496. *(int16_t *) out = int16_val;
  497. break;
  498. case 'q':
  499. uint16_val = l_get_u16(start);
  500. *(uint16_t *) out = uint16_val;
  501. break;
  502. case 'i':
  503. int32_val = l_get_s32(start);
  504. *(int32_t *) out = int32_val;
  505. break;
  506. case 'h':
  507. case 'u':
  508. uint32_val = l_get_u32(start);
  509. *(uint32_t *) out = uint32_val;
  510. break;
  511. case 'x':
  512. int64_val = l_get_s64(start);
  513. *(int64_t *) out = int64_val;
  514. break;
  515. case 't':
  516. uint64_val = l_get_u64(start);
  517. *(uint64_t *) out = uint64_val;
  518. break;
  519. case 'd':
  520. uint64_val = l_get_u64(start);
  521. *(uint64_t *) out = uint64_val;
  522. break;
  523. }
  524. return true;
  525. }
  526. bool _gvariant_iter_enter_struct(struct l_dbus_message_iter *iter,
  527. struct l_dbus_message_iter *structure)
  528. {
  529. bool is_dict = iter->sig_start[iter->sig_pos] == '{';
  530. bool is_struct = iter->sig_start[iter->sig_pos] == '(';
  531. const char *sig_start = iter->sig_start + iter->sig_pos + 1;
  532. const char *sig_end;
  533. const void *start;
  534. size_t item_size;
  535. enum dbus_container_type type;
  536. if (!is_dict && !is_struct)
  537. return false;
  538. start = next_item(iter, &item_size);
  539. if (!start)
  540. return false;
  541. /* For ARRAY containers the sig_pos is never incremented */
  542. if (iter->container_type == DBUS_CONTAINER_TYPE_ARRAY)
  543. sig_end = iter->sig_start + iter->sig_len - 1;
  544. else
  545. sig_end = iter->sig_start + iter->sig_pos - 1;
  546. type = is_dict ? DBUS_CONTAINER_TYPE_DICT_ENTRY :
  547. DBUS_CONTAINER_TYPE_STRUCT;
  548. return gvariant_iter_init_internal(structure, iter->message,
  549. type, sig_start, sig_end,
  550. start, item_size);
  551. }
  552. bool _gvariant_iter_enter_variant(struct l_dbus_message_iter *iter,
  553. struct l_dbus_message_iter *variant)
  554. {
  555. size_t item_size;
  556. const void *start, *end, *nul;
  557. char signature[256];
  558. if (iter->sig_start[iter->sig_pos] != 'v')
  559. return false;
  560. start = next_item(iter, &item_size);
  561. if (!start)
  562. return false;
  563. /* Find the signature */
  564. end = start + item_size;
  565. nul = memrchr(start, 0, end - start);
  566. if (!nul)
  567. return false;
  568. if (end - nul - 1 > 255)
  569. return false;
  570. memcpy(signature, nul + 1, end - nul - 1);
  571. signature[end - nul - 1] = '\0';
  572. if (_gvariant_num_children(signature) != 1)
  573. return false;
  574. return gvariant_iter_init_internal(variant, iter->message,
  575. DBUS_CONTAINER_TYPE_VARIANT,
  576. nul + 1, end,
  577. start, nul - start);
  578. }
  579. bool _gvariant_iter_enter_array(struct l_dbus_message_iter *iter,
  580. struct l_dbus_message_iter *array)
  581. {
  582. const char *sig_start;
  583. const char *sig_end;
  584. size_t item_size;
  585. const void *start;
  586. if (iter->sig_start[iter->sig_pos] != 'a')
  587. return false;
  588. sig_start = iter->sig_start + iter->sig_pos + 1;
  589. start = next_item(iter, &item_size);
  590. if (!start)
  591. return false;
  592. /* For ARRAY containers the sig_pos is never incremented */
  593. if (iter->container_type == DBUS_CONTAINER_TYPE_ARRAY)
  594. sig_end = iter->sig_start + iter->sig_len;
  595. else
  596. sig_end = iter->sig_start + iter->sig_pos;
  597. return gvariant_iter_init_internal(array, iter->message,
  598. DBUS_CONTAINER_TYPE_ARRAY,
  599. sig_start, sig_end,
  600. start, item_size);
  601. }
  602. bool _gvariant_iter_skip_entry(struct l_dbus_message_iter *iter)
  603. {
  604. size_t size;
  605. if (!next_item(iter, &size))
  606. return false;
  607. return true;
  608. }
  609. struct dbus_builder {
  610. struct l_string *signature;
  611. void *body;
  612. size_t body_size;
  613. size_t body_pos;
  614. struct l_queue *containers;
  615. struct {
  616. struct container *container;
  617. int sig_end;
  618. size_t body_pos;
  619. size_t offset_index;
  620. bool variable_is_last : 1;
  621. } mark;
  622. };
  623. struct container {
  624. size_t *offsets;
  625. size_t offsets_size;
  626. size_t offset_index;
  627. size_t start;
  628. bool variable_is_last : 1;
  629. enum dbus_container_type type;
  630. char signature[256];
  631. uint8_t sigindex;
  632. };
  633. static inline size_t grow_body(struct dbus_builder *builder,
  634. size_t len, unsigned int alignment)
  635. {
  636. size_t size = align_len(builder->body_pos, alignment);
  637. if (size + len > builder->body_size) {
  638. builder->body = l_realloc(builder->body, size + len);
  639. builder->body_size = size + len;
  640. }
  641. if (size - builder->body_pos > 0)
  642. memset(builder->body + builder->body_pos, 0,
  643. size - builder->body_pos);
  644. builder->body_pos = size + len;
  645. return size;
  646. }
  647. static inline bool grow_offsets(struct container *container)
  648. {
  649. size_t needed;
  650. if (container->offset_index < container->offsets_size)
  651. return true;
  652. needed = container->offsets_size * 2;
  653. if (needed > USHRT_MAX)
  654. return false;
  655. if (needed == 0)
  656. needed = 8;
  657. container->offsets = l_realloc(container->offsets,
  658. needed * sizeof(size_t));
  659. container->offsets_size = needed;
  660. return true;
  661. }
  662. static struct container *container_new(enum dbus_container_type type,
  663. const char *signature, size_t start)
  664. {
  665. struct container *ret;
  666. ret = l_new(struct container, 1);
  667. ret->type = type;
  668. strcpy(ret->signature, signature);
  669. ret->start = start;
  670. return ret;
  671. }
  672. static void container_free(struct container *container)
  673. {
  674. l_free(container->offsets);
  675. l_free(container);
  676. }
  677. static void container_append_struct_offsets(struct container *container,
  678. struct dbus_builder *builder)
  679. {
  680. size_t offset_size;
  681. int i;
  682. size_t start;
  683. if (container->variable_is_last)
  684. container->offset_index -= 1;
  685. if (container->offset_index == 0)
  686. return;
  687. offset_size = offset_length(builder->body_pos,
  688. container->offset_index);
  689. i = container->offset_index - 1;
  690. start = grow_body(builder, offset_size * container->offset_index, 1);
  691. for (i = container->offset_index - 1; i >= 0; i--) {
  692. write_word_le(builder->body + start,
  693. container->offsets[i], offset_size);
  694. start += offset_size;
  695. }
  696. }
  697. static void container_append_array_offsets(struct container *container,
  698. struct dbus_builder *builder)
  699. {
  700. size_t offset_size;
  701. unsigned int i;
  702. size_t start;
  703. if (container->offset_index == 0)
  704. return;
  705. offset_size = offset_length(builder->body_pos,
  706. container->offset_index);
  707. start = grow_body(builder, offset_size * container->offset_index, 1);
  708. for (i = 0; i < container->offset_index; i++) {
  709. write_word_le(builder->body + start,
  710. container->offsets[i], offset_size);
  711. start += offset_size;
  712. }
  713. }
  714. struct dbus_builder *_gvariant_builder_new(void *body, size_t body_size)
  715. {
  716. struct dbus_builder *builder;
  717. struct container *root;
  718. builder = l_new(struct dbus_builder, 1);
  719. builder->signature = l_string_new(63);
  720. builder->containers = l_queue_new();
  721. root = container_new(DBUS_CONTAINER_TYPE_STRUCT, "", 0);
  722. l_queue_push_head(builder->containers, root);
  723. builder->body = body;
  724. builder->body_size = body_size;
  725. builder->body_pos = body_size;
  726. builder->mark.container = root;
  727. return builder;
  728. }
  729. void _gvariant_builder_free(struct dbus_builder *builder)
  730. {
  731. if (unlikely(!builder))
  732. return;
  733. l_string_free(builder->signature);
  734. l_queue_destroy(builder->containers,
  735. (l_queue_destroy_func_t) container_free);
  736. l_free(builder->body);
  737. l_free(builder);
  738. }
  739. static bool enter_struct_dict_common(struct dbus_builder *builder,
  740. const char *signature,
  741. enum dbus_container_type type,
  742. const char open,
  743. const char close)
  744. {
  745. size_t qlen = l_queue_length(builder->containers);
  746. struct container *container = l_queue_peek_head(builder->containers);
  747. int alignment;
  748. size_t start;
  749. if (qlen == 1) {
  750. if (l_string_length(builder->signature) +
  751. strlen(signature) + 2 > 255)
  752. return false;
  753. } else {
  754. /* Verify Signatures Match */
  755. char expect[256];
  756. const char *start;
  757. const char *end;
  758. start = container->signature + container->sigindex;
  759. end = validate_next_type(start, &alignment) - 1;
  760. if (*start != open || *end != close)
  761. return false;
  762. memcpy(expect, start + 1, end - start - 1);
  763. expect[end - start - 1] = '\0';
  764. if (strcmp(expect, signature))
  765. return false;
  766. }
  767. alignment = _gvariant_get_alignment(signature);
  768. start = grow_body(builder, 0, alignment);
  769. container = container_new(type, signature, start);
  770. l_queue_push_head(builder->containers, container);
  771. return true;
  772. }
  773. bool _gvariant_builder_enter_struct(struct dbus_builder *builder,
  774. const char *signature)
  775. {
  776. if (signature[0] && !_gvariant_valid_signature(signature))
  777. return false;
  778. return enter_struct_dict_common(builder, signature,
  779. DBUS_CONTAINER_TYPE_STRUCT, '(', ')');
  780. }
  781. bool _gvariant_builder_enter_dict(struct dbus_builder *builder,
  782. const char *signature)
  783. {
  784. if (_gvariant_num_children(signature) != 2)
  785. return false;
  786. if (!strchr(simple_types, signature[0]))
  787. return false;
  788. return enter_struct_dict_common(builder, signature,
  789. DBUS_CONTAINER_TYPE_DICT_ENTRY,
  790. '{', '}');
  791. }
  792. static bool leave_struct_dict_common(struct dbus_builder *builder,
  793. enum dbus_container_type type,
  794. const char open,
  795. const char close)
  796. {
  797. struct container *container = l_queue_peek_head(builder->containers);
  798. size_t qlen = l_queue_length(builder->containers);
  799. struct container *parent;
  800. if (unlikely(qlen <= 1))
  801. return false;
  802. if (unlikely(container->type != type))
  803. return false;
  804. l_queue_pop_head(builder->containers);
  805. qlen -= 1;
  806. parent = l_queue_peek_head(builder->containers);
  807. if (_gvariant_is_fixed_size(container->signature)) {
  808. int alignment = _gvariant_get_alignment(container->signature);
  809. grow_body(builder, 0, alignment);
  810. /* Empty struct or "unit type" is encoded as a zero byte */
  811. if (container->signature[0] == '\0') {
  812. size_t start = grow_body(builder, 1, 1);
  813. memset(builder->body + start, 0, 1);
  814. }
  815. parent->variable_is_last = false;
  816. } else {
  817. size_t offset;
  818. if (!grow_offsets(parent))
  819. return false;
  820. container_append_struct_offsets(container, builder);
  821. offset = builder->body_pos - parent->start;
  822. parent->offsets[parent->offset_index++] = offset;
  823. parent->variable_is_last = true;
  824. }
  825. if (qlen == 1)
  826. l_string_append_printf(builder->signature, "%c%s%c",
  827. open,
  828. container->signature,
  829. close);
  830. else if (parent->type != DBUS_CONTAINER_TYPE_ARRAY)
  831. parent->sigindex += strlen(container->signature) + 2;
  832. container_free(container);
  833. return true;
  834. }
  835. bool _gvariant_builder_leave_struct(struct dbus_builder *builder)
  836. {
  837. return leave_struct_dict_common(builder, DBUS_CONTAINER_TYPE_STRUCT,
  838. '(', ')');
  839. }
  840. bool _gvariant_builder_leave_dict(struct dbus_builder *builder)
  841. {
  842. return leave_struct_dict_common(builder,
  843. DBUS_CONTAINER_TYPE_DICT_ENTRY,
  844. '{', '}');
  845. }
  846. bool _gvariant_builder_enter_variant(struct dbus_builder *builder,
  847. const char *signature)
  848. {
  849. size_t qlen = l_queue_length(builder->containers);
  850. struct container *container = l_queue_peek_head(builder->containers);
  851. size_t start;
  852. if (_gvariant_num_children(signature) != 1)
  853. return false;
  854. if (qlen == 1) {
  855. if (l_string_length(builder->signature) + 1 > 255)
  856. return false;
  857. } else if (container->signature[container->sigindex] != 'v')
  858. return false;
  859. start = grow_body(builder, 0, 8);
  860. container = container_new(DBUS_CONTAINER_TYPE_VARIANT,
  861. signature, start);
  862. l_queue_push_head(builder->containers, container);
  863. return true;
  864. }
  865. bool _gvariant_builder_leave_variant(struct dbus_builder *builder)
  866. {
  867. struct container *container = l_queue_peek_head(builder->containers);
  868. size_t qlen = l_queue_length(builder->containers);
  869. struct container *parent;
  870. size_t start;
  871. size_t siglen;
  872. size_t offset;
  873. if (unlikely(qlen <= 1))
  874. return false;
  875. if (unlikely(container->type != DBUS_CONTAINER_TYPE_VARIANT))
  876. return false;
  877. l_queue_pop_head(builder->containers);
  878. qlen -= 1;
  879. parent = l_queue_peek_head(builder->containers);
  880. siglen = strlen(container->signature);
  881. start = grow_body(builder, siglen + 1, 1);
  882. memset(builder->body + start, 0, 1);
  883. memcpy(builder->body + start + 1, container->signature, siglen);
  884. if (!grow_offsets(parent))
  885. return false;
  886. offset = builder->body_pos - parent->start;
  887. parent->offsets[parent->offset_index++] = offset;
  888. parent->variable_is_last = true;
  889. if (qlen == 1)
  890. l_string_append_c(builder->signature, 'v');
  891. else if (parent->type != DBUS_CONTAINER_TYPE_ARRAY)
  892. parent->sigindex += 1;
  893. container_free(container);
  894. return true;
  895. }
  896. bool _gvariant_builder_enter_array(struct dbus_builder *builder,
  897. const char *signature)
  898. {
  899. size_t qlen = l_queue_length(builder->containers);
  900. struct container *container = l_queue_peek_head(builder->containers);
  901. size_t start;
  902. int alignment;
  903. if (_gvariant_num_children(signature) != 1)
  904. return false;
  905. if (qlen == 1) {
  906. if (l_string_length(builder->signature) +
  907. strlen(signature) + 1 > 255)
  908. return false;
  909. } else {
  910. /* Verify Signatures Match */
  911. char expect[256];
  912. const char *start;
  913. const char *end;
  914. start = container->signature + container->sigindex;
  915. end = validate_next_type(start, &alignment);
  916. if (*start != 'a')
  917. return false;
  918. memcpy(expect, start + 1, end - start - 1);
  919. expect[end - start - 1] = '\0';
  920. if (strcmp(expect, signature))
  921. return false;
  922. }
  923. alignment = _gvariant_get_alignment(signature);
  924. start = grow_body(builder, 0, alignment);
  925. container = container_new(DBUS_CONTAINER_TYPE_ARRAY, signature, start);
  926. l_queue_push_head(builder->containers, container);
  927. return true;
  928. }
  929. bool _gvariant_builder_leave_array(struct dbus_builder *builder)
  930. {
  931. struct container *container = l_queue_peek_head(builder->containers);
  932. size_t qlen = l_queue_length(builder->containers);
  933. struct container *parent;
  934. size_t offset;
  935. if (unlikely(qlen <= 1))
  936. return false;
  937. if (unlikely(container->type != DBUS_CONTAINER_TYPE_ARRAY))
  938. return false;
  939. l_queue_pop_head(builder->containers);
  940. qlen -= 1;
  941. parent = l_queue_peek_head(builder->containers);
  942. if (!_gvariant_is_fixed_size(container->signature))
  943. container_append_array_offsets(container, builder);
  944. if (!grow_offsets(parent))
  945. return false;
  946. offset = builder->body_pos - parent->start;
  947. parent->offsets[parent->offset_index++] = offset;
  948. parent->variable_is_last = true;
  949. if (qlen == 1)
  950. l_string_append_printf(builder->signature, "a%s",
  951. container->signature);
  952. else if (parent->type != DBUS_CONTAINER_TYPE_ARRAY)
  953. parent->sigindex += strlen(container->signature) + 1;
  954. container_free(container);
  955. return true;
  956. }
  957. bool _gvariant_builder_append_basic(struct dbus_builder *builder,
  958. char type, const void *value)
  959. {
  960. struct container *container = l_queue_peek_head(builder->containers);
  961. size_t start;
  962. unsigned int alignment;
  963. size_t len;
  964. size_t offset;
  965. if (unlikely(!builder))
  966. return false;
  967. if (unlikely(!strchr(simple_types, type)))
  968. return false;
  969. alignment = get_basic_alignment(type);
  970. if (!alignment)
  971. return false;
  972. if (l_queue_length(builder->containers) == 1)
  973. l_string_append_c(builder->signature, type);
  974. else if (container->signature[container->sigindex] != type)
  975. return false;
  976. len = get_basic_fixed_size(type);
  977. if (len) {
  978. start = grow_body(builder, len, alignment);
  979. memcpy(builder->body + start, value, len);
  980. container->variable_is_last = false;
  981. if (container->type != DBUS_CONTAINER_TYPE_ARRAY)
  982. container->sigindex += 1;
  983. return true;
  984. }
  985. if (!grow_offsets(container))
  986. return false;
  987. len = strlen(value) + 1;
  988. start = grow_body(builder, len, alignment);
  989. memcpy(builder->body + start, value, len);
  990. offset = builder->body_pos - container->start;
  991. container->offsets[container->offset_index++] = offset;
  992. container->variable_is_last = true;
  993. if (container->type != DBUS_CONTAINER_TYPE_ARRAY)
  994. container->sigindex += 1;
  995. return true;
  996. }
  997. bool _gvariant_builder_mark(struct dbus_builder *builder)
  998. {
  999. struct container *container = l_queue_peek_head(builder->containers);
  1000. builder->mark.container = container;
  1001. if (l_queue_length(builder->containers) == 1)
  1002. builder->mark.sig_end = l_string_length(builder->signature);
  1003. else
  1004. builder->mark.sig_end = container->sigindex;
  1005. builder->mark.body_pos = builder->body_pos;
  1006. builder->mark.offset_index = container->offset_index;
  1007. builder->mark.variable_is_last = container->variable_is_last;
  1008. return true;
  1009. }
  1010. bool _gvariant_builder_rewind(struct dbus_builder *builder)
  1011. {
  1012. struct container *container;
  1013. while ((container = l_queue_peek_head(builder->containers)) !=
  1014. builder->mark.container) {
  1015. container_free(container);
  1016. l_queue_pop_head(builder->containers);
  1017. }
  1018. builder->body_pos = builder->mark.body_pos;
  1019. container->offset_index = builder->mark.offset_index;
  1020. container->variable_is_last = builder->mark.variable_is_last;
  1021. if (l_queue_length(builder->containers) == 1)
  1022. l_string_truncate(builder->signature, builder->mark.sig_end);
  1023. else
  1024. container->sigindex = builder->mark.sig_end;
  1025. return true;
  1026. }
  1027. char *_gvariant_builder_finish(struct dbus_builder *builder,
  1028. void **body, size_t *body_size)
  1029. {
  1030. char *signature;
  1031. struct container *root;
  1032. uint8_t *variant_buf;
  1033. size_t size;
  1034. if (unlikely(!builder))
  1035. return NULL;
  1036. if (unlikely(l_queue_length(builder->containers) != 1))
  1037. return NULL;
  1038. root = l_queue_peek_head(builder->containers);
  1039. signature = l_string_unwrap(builder->signature);
  1040. builder->signature = NULL;
  1041. if (_gvariant_is_fixed_size(signature)) {
  1042. int alignment = _gvariant_get_alignment(signature);
  1043. grow_body(builder, 0, alignment);
  1044. /* Empty struct or "unit type" is encoded as a zero byte */
  1045. if (signature[0] == '\0') {
  1046. size_t start = grow_body(builder, 1, 1);
  1047. memset(builder->body + start, 0, 1);
  1048. }
  1049. } else
  1050. container_append_struct_offsets(root, builder);
  1051. /*
  1052. * Make sure there's enough space after the body for the variant
  1053. * signature written here but not included in the body size and
  1054. * one framing offset value to be written in
  1055. * _gvariant_message_finalize.
  1056. */
  1057. size = 3 + strlen(signature) + 8;
  1058. if (builder->body_pos + size > builder->body_size)
  1059. builder->body = l_realloc(builder->body,
  1060. builder->body_pos + size);
  1061. variant_buf = builder->body + builder->body_pos;
  1062. *variant_buf++ = 0;
  1063. *variant_buf++ = '(';
  1064. variant_buf = mempcpy(variant_buf, signature, strlen(signature));
  1065. *variant_buf++ = ')';
  1066. *body = builder->body;
  1067. *body_size = builder->body_pos;
  1068. builder->body = NULL;
  1069. builder->body_size = 0;
  1070. return signature;
  1071. }
  1072. /*
  1073. * Write the header's framing offset after the body variant which is the
  1074. * last piece of data in the message after the header, the padding and
  1075. * the builder has written the message body.
  1076. */
  1077. size_t _gvariant_message_finalize(size_t header_end,
  1078. void *body, size_t body_size,
  1079. const char *signature)
  1080. {
  1081. size_t offset_start;
  1082. size_t offset_size;
  1083. offset_start = body_size + 3 + strlen(signature);
  1084. offset_size = offset_length(align_len(header_end, 8) + offset_start, 1);
  1085. write_word_le(body + offset_start, header_end, offset_size);
  1086. return align_len(header_end, 8) + offset_start + offset_size;
  1087. }