Skip to content

Commit 856a40e

Browse files
committed
Fix big endian issues writing and reading .LYB files
The print and parse routines which handle .LYB files assume a little endian CPU. This means libyang is failing when it is compiled for a big endian target. For example consider the code: lyb_write(out, (uint8_t *)&mod_count, 2, lybs); mod_count is an integer and on a typical 32 bit big endian target its format in memory is (byte0(MSB) byte1 byte2 byte3(LSB)) meaning if mod_count has a value of 1 the first three bytes of mod_count are zero, and as the routine only write the first two bytes, it writes out 0. This effectively corrupts the .LYB file. This patch modifies the routines to write and read .LYB files to use endian agnostic methods to access data in a .LYB file.
1 parent 6341aea commit 856a40e

File tree

3 files changed

+49
-32
lines changed

3 files changed

+49
-32
lines changed

src/parser_lyb.c

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <stdlib.h>
1818
#include <string.h>
1919
#include <inttypes.h>
20+
#include <endian.h>
2021

2122
#include "libyang.h"
2223
#include "common.h"
@@ -32,7 +33,7 @@ lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
3233
{
3334
int ret = 0, i, empty_chunk_i;
3435
size_t to_read;
35-
LYB_META meta;
36+
uint8_t meta_buf[LYB_META_BYTES];
3637

3738
assert(data && lybs);
3839

@@ -76,12 +77,9 @@ lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
7677

7778
if (empty_chunk_i > -1) {
7879
/* read the next chunk meta information */
79-
memcpy(&meta, data + ret, LYB_META_BYTES);
80-
lybs->written[empty_chunk_i] = 0;
81-
lybs->inner_chunks[empty_chunk_i] = 0;
82-
83-
memcpy(&lybs->written[empty_chunk_i], &meta, LYB_SIZE_BYTES);
84-
memcpy(&lybs->inner_chunks[empty_chunk_i], ((uint8_t *)&meta) + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
80+
memcpy(meta_buf, data + ret, LYB_META_BYTES);
81+
lybs->written[empty_chunk_i] = meta_buf[0];
82+
lybs->inner_chunks[empty_chunk_i] = meta_buf[1];
8583

8684
/* remember whether there is a following chunk or not */
8785
lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
@@ -113,7 +111,9 @@ lyb_read_number(uint64_t *num, size_t bytes, const char *data, struct lyb_state
113111
static int
114112
lyb_read_enum(uint64_t *enum_idx, uint32_t count, const char *data, struct lyb_state *lybs)
115113
{
114+
int ret = 0;
116115
size_t bytes;
116+
uint64_t tmp_enum = 0;
117117

118118
if (count < (2 << 8)) {
119119
bytes = 1;
@@ -125,18 +125,24 @@ lyb_read_enum(uint64_t *enum_idx, uint32_t count, const char *data, struct lyb_s
125125
bytes = 4;
126126
}
127127

128-
return lyb_read_number(enum_idx, bytes, data, lybs);
128+
/* The enum is always read into a uint64_t buffer */
129+
ret = lyb_read_number(&tmp_enum, bytes, data, lybs);
130+
*enum_idx = le64toh(tmp_enum);
131+
132+
return ret;
129133
}
130134

131135
static int
132136
lyb_read_string(const char *data, char **str, int with_length, struct lyb_state *lybs)
133137
{
134138
int next_chunk = 0, r, ret = 0;
135139
size_t len = 0, cur_len;
140+
uint8_t len_buf[2];
136141

137142
if (with_length) {
138-
ret += (r = lyb_read(data, (uint8_t *)&len, 2, lybs));
143+
ret += (r = lyb_read(data, len_buf, 2, lybs));
139144
LYB_HAVE_READ_GOTO(r, data, error);
145+
len = len_buf[0] | (len_buf[1] << 8);
140146
} else {
141147
/* read until the end of this subtree */
142148
len = lybs->written[lybs->used - 1];
@@ -190,7 +196,7 @@ lyb_read_stop_subtree(struct lyb_state *lybs)
190196
static int
191197
lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
192198
{
193-
LYB_META meta;
199+
uint8_t meta_buf[LYB_META_BYTES];
194200

195201
if (lybs->used == lybs->size) {
196202
lybs->size += LYB_STATE_STEP;
@@ -200,14 +206,11 @@ lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
200206
LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(NULL), -1);
201207
}
202208

203-
memcpy(&meta, data, LYB_META_BYTES);
209+
memcpy(meta_buf, data, LYB_META_BYTES);
204210

205211
++lybs->used;
206-
lybs->written[lybs->used - 1] = 0;
207-
lybs->inner_chunks[lybs->used - 1] = 0;
208-
209-
memcpy(&lybs->written[lybs->used - 1], &meta, LYB_SIZE_BYTES);
210-
memcpy(&lybs->inner_chunks[lybs->used - 1], ((uint8_t *)&meta) + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
212+
lybs->written[lybs->used - 1] = meta_buf[0];
213+
lybs->inner_chunks[lybs->used - 1] = meta_buf[LYB_SIZE_BYTES];
211214
lybs->position[lybs->used - 1] = (lybs->written[lybs->used - 1] == LYB_SIZE_MAX ? 1 : 0);
212215

213216
return LYB_META_BYTES;
@@ -219,14 +222,16 @@ lyb_parse_model(struct ly_ctx *ctx, const char *data, const struct lys_module **
219222
int r, ret = 0;
220223
char *mod_name = NULL, mod_rev[11];
221224
uint16_t rev = 0;
225+
uint8_t tmp_buf[2];
222226

223227
/* model name */
224228
ret += (r = lyb_read_string(data, &mod_name, 1, lybs));
225229
LYB_HAVE_READ_GOTO(r, data, error);
226230

227231
/* revision */
228-
ret += (r = lyb_read(data, (uint8_t *)&rev, sizeof rev, lybs));
232+
ret += (r = lyb_read(data, tmp_buf, sizeof tmp_buf, lybs));
229233
LYB_HAVE_READ_GOTO(r, data, error);
234+
rev = tmp_buf[0] | (tmp_buf[1] << 8);
230235

231236
if (rev) {
232237
sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, (rev & 0x001F));
@@ -430,15 +435,18 @@ lyb_parse_val_1(struct ly_ctx *ctx, struct lys_type *type, LY_DATA_TYPE value_ty
430435
case LY_TYPE_INT16:
431436
case LY_TYPE_UINT16:
432437
ret = lyb_read_number((uint64_t *)&value->uint16, 2, data, lybs);
438+
value->uint16 = le16toh(value->uint16);
433439
break;
434440
case LY_TYPE_INT32:
435441
case LY_TYPE_UINT32:
436442
ret = lyb_read_number((uint64_t *)&value->uint32, 4, data, lybs);
443+
value->uint32 = le32toh(value->uint32);
437444
break;
438445
case LY_TYPE_DEC64:
439446
case LY_TYPE_INT64:
440447
case LY_TYPE_UINT64:
441448
ret = lyb_read_number((uint64_t *)&value->uint64, 8, data, lybs);
449+
value->uint64 = le64toh(value->uint64);
442450
break;
443451
default:
444452
return -1;
@@ -1101,10 +1109,12 @@ static int
11011109
lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
11021110
{
11031111
int i, r, ret = 0;
1112+
uint8_t mod_count_buf[2];
11041113

11051114
/* read model count */
1106-
ret += (r = lyb_read(data, (uint8_t *)&lybs->mod_count, 2, lybs));
1115+
ret += (r = lyb_read(data, mod_count_buf, 2, lybs));
11071116
LYB_HAVE_READ_RETURN(r, data, -1);
1117+
lybs->mod_count = mod_count_buf[0] | (mod_count_buf[1] << 8);
11081118

11091119
lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
11101120
LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);

src/printer_lyb.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <string.h>
1919
#include <assert.h>
2020
#include <stdint.h>
21+
#include <endian.h>
2122

2223
#include "common.h"
2324
#include "printer.h"
@@ -323,7 +324,7 @@ lyb_write(struct lyout *out, const uint8_t *buf, size_t count, struct lyb_state
323324
{
324325
int ret, i, full_chunk_i;
325326
size_t r, to_write;
326-
LYB_META meta;
327+
uint8_t meta_buf[LYB_META_BYTES];
327328

328329
assert(out && lybs);
329330

@@ -359,10 +360,10 @@ lyb_write(struct lyout *out, const uint8_t *buf, size_t count, struct lyb_state
359360

360361
if (full_chunk_i > -1) {
361362
/* write the meta information (inner chunk count and chunk size) */
362-
memcpy(&meta, &lybs->written[full_chunk_i], LYB_SIZE_BYTES);
363-
memcpy(((uint8_t *)&meta) + LYB_SIZE_BYTES, &lybs->inner_chunks[full_chunk_i], LYB_INCHUNK_BYTES);
363+
meta_buf[0] = lybs->written[full_chunk_i] & 0xFF;
364+
meta_buf[1] = lybs->inner_chunks[full_chunk_i] & 0xFF;
364365

365-
r = ly_write_skipped(out, lybs->position[full_chunk_i], (char *)&meta, LYB_META_BYTES);
366+
r = ly_write_skipped(out, lybs->position[full_chunk_i], (char *)meta_buf, LYB_META_BYTES);
366367
if (r < LYB_META_BYTES) {
367368
return -1;
368369
}
@@ -397,13 +398,13 @@ static int
397398
lyb_write_stop_subtree(struct lyout *out, struct lyb_state *lybs)
398399
{
399400
int r;
400-
LYB_META meta;
401+
uint8_t meta_buf[LYB_META_BYTES];
401402

402403
/* write the meta chunk information */
403-
memcpy(&meta, &lybs->written[lybs->used - 1], LYB_SIZE_BYTES);
404-
memcpy(((uint8_t *)&meta) + LYB_SIZE_BYTES, &lybs->inner_chunks[lybs->used - 1], LYB_INCHUNK_BYTES);
404+
meta_buf[0] = lybs->written[lybs->used - 1] & 0xFF;
405+
meta_buf[1] = lybs->inner_chunks[lybs->used - 1] & 0xFF;
405406

406-
r = ly_write_skipped(out, lybs->position[lybs->used - 1], (char *)&meta, LYB_META_BYTES);
407+
r = ly_write_skipped(out, lybs->position[lybs->used - 1], (char *)&meta_buf, LYB_META_BYTES);
407408
if (r < LYB_META_BYTES) {
408409
return -1;
409410
}
@@ -448,9 +449,13 @@ lyb_write_number(uint64_t num, size_t bytes, struct lyout *out, struct lyb_state
448449
size_t i;
449450
uint8_t byte;
450451

452+
num = htole64(num);
451453
for (i = 0; i < bytes; ++i) {
452454
byte = *(((uint8_t *)&num) + i);
453455
ret += lyb_write(out, &byte, 1, lybs);
456+
if (ret < 0) {
457+
break;
458+
}
454459
}
455460

456461
return ret;
@@ -489,7 +494,7 @@ lyb_write_string(const char *str, size_t str_len, int with_length, struct lyout
489494

490495
if (with_length) {
491496
/* print length on 2 bytes */
492-
ret += (r = lyb_write(out, (uint8_t *)&str_len, 2, lybs));
497+
ret += (r = lyb_write_number(str_len, 2, out, lybs));
493498
if (r < 0) {
494499
return -1;
495500
}
@@ -534,8 +539,7 @@ lyb_print_model(struct lyout *out, const struct lys_module *mod, struct lyb_stat
534539

535540
revision |= r;
536541
}
537-
538-
ret += (r = lyb_write(out, (uint8_t *)&revision, sizeof revision, lybs));
542+
ret += (r = lyb_write_number(revision, sizeof revision, out, lybs));
539543
if (r < 0) {
540544
return -1;
541545
}
@@ -625,7 +629,7 @@ lyb_print_data_models(struct lyout *out, const struct lyd_node *root, struct lyb
625629
}
626630

627631
/* now write module count on 2 bytes */
628-
ret += lyb_write(out, (uint8_t *)&mod_count, 2, lybs);
632+
ret += lyb_write_number(mod_count, 2, out, lybs);
629633

630634
/* and all the used models */
631635
for (i = 0; i < mod_count; ++i) {

src/tree_data.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7335,6 +7335,7 @@ lyd_lyb_data_length(const char *data)
73357335
{
73367336
const char *ptr;
73377337
uint16_t i, mod_count, str_len;
7338+
uint8_t tmp_buf[2];
73387339
LYB_META meta;
73397340

73407341
if (!data) {
@@ -7353,13 +7354,15 @@ lyd_lyb_data_length(const char *data)
73537354
++ptr;
73547355

73557356
/* models */
7356-
memcpy(&mod_count, ptr, 2);
7357+
memcpy(tmp_buf, ptr, 2);
73577358
ptr += 2;
7359+
mod_count = tmp_buf[0] | (tmp_buf[1] << 8);
73587360

73597361
for (i = 0; i < mod_count; ++i) {
73607362
/* model name */
7361-
memcpy(&str_len, ptr, 2);
7363+
memcpy(tmp_buf, ptr, 2);
73627364
ptr += 2;
7365+
str_len = tmp_buf[0] | (tmp_buf[1] << 8);
73637366

73647367
ptr += str_len;
73657368

0 commit comments

Comments
 (0)