Rizin
unix-like reverse engineering framework and cli tools
protobuf.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2017-2019 deroad <wargio@libero.it>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_util.h>
5 #include <rz_cons.h>
6 
7 typedef float ft32;
8 typedef double ft64;
9 
10 #define WIRE_VARINT 0 // int32, int64, uint32, uint64, sint32, sint64, bool, enum
11 #define WIRE_64_BIT 1 // fixed64, sfixed64, double
12 #define WIRE_LEN_DELIM 2 // string, bytes, embedded messages, packed repeated fields
13 #define WIRE_START_GRP 3 // groups (deprecated)
14 #define WIRE_END_GRP 4 // groups (deprecated)
15 #define WIRE_32_BIT 5 // fixed32, sfixed32, float
16 
17 static const char *s_wire(const ut8 byte) {
18  switch (byte) {
19  case WIRE_VARINT:
20  return "[VARINT]";
21  case WIRE_64_BIT:
22  return "[64_BIT]";
23  case WIRE_LEN_DELIM:
24  return "[LEN_DELIM]";
25  case WIRE_START_GRP:
26  return "[START_GROUP]";
27  case WIRE_END_GRP:
28  return "[END_GROUP]";
29  case WIRE_32_BIT:
30  return "[32_BIT]";
31  default:
32  return "[UNKN]";
33  }
34 }
35 
36 static void pad(RzStrBuf *sb, ut32 count) {
37  ut32 i;
38  for (i = 0; i < count; i++) {
39  rz_strbuf_appendf(sb, " ");
40  }
41 }
42 
43 static bool is_string(const ut8 *start, const ut8 *end) {
44  while (start < end) {
45  // TODO UTF-8 Support.
46  if (!IS_PRINTABLE(*start)) {
47  return false;
48  }
49  start++;
50  }
51  return true;
52 }
53 
54 static void decode_array(RzStrBuf *sb, const ut8 *start, const ut8 *end) {
55  while (start < end) {
56  rz_strbuf_appendf(sb, "%02x ", *start);
57  start++;
58  }
59  rz_strbuf_appendf(sb, "\n");
60 }
61 
62 static void decode_buffer(RzStrBuf *sb, const ut8 *start, const ut8 *end, ut32 padcnt, bool debug) {
63  size_t bytes_read = 0;
64  ut32 var32 = 0;
65  ut64 var64 = 0;
66  const ut8 *buffer = start;
67  while (buffer >= start && buffer < end) {
68  if (!*buffer) {
69  return;
70  }
71  // ut8 byte = *buffer;
72  ut8 number = buffer[0] >> 3;
73  ut8 wire = buffer[0] & 0x7;
74  buffer++;
76  eprintf("\ninvalid buffer pointer.\n");
77  break;
78  } else if (wire > WIRE_32_BIT) {
79  eprintf("\nunknown wire id (%u).\n", wire);
80  return;
81  }
82  if (wire != WIRE_END_GRP) {
83  pad(sb, padcnt);
84  if (debug) {
85  rz_strbuf_appendf(sb, "%u %-13s", number, s_wire(wire));
86  } else {
87  rz_strbuf_appendf(sb, "%u", number);
88  }
89  }
90  switch (wire) {
91  case WIRE_VARINT: {
92  st64 *i = (st64 *)&var64;
93  bytes_read = read_u64_leb128(buffer, end, &var64);
94  rz_strbuf_appendf(sb, ": %" PFMT64u " | %" PFMT64d "\n", var64, *i);
95  } break;
96  case WIRE_64_BIT: {
97  ft64 *f = (ft64 *)&var64;
98  st64 *i = (st64 *)&var64;
99  bytes_read = read_u64_leb128(buffer, end, &var64);
100  rz_strbuf_appendf(sb, ": %" PFMT64u " | %" PFMT64d " | %f\n", var64, *i, *f);
101  } break;
102  case WIRE_LEN_DELIM: {
103  bytes_read = read_u64_leb128(buffer, end, &var64);
104  const ut8 *ps = buffer + bytes_read;
105  const ut8 *pe = ps + var64;
106  if (ps > buffer && pe <= end) {
107  if (is_string(ps, pe)) {
108  rz_strbuf_appendf(sb, ": \"%.*s\"\n", (int)var64, (const char *)ps);
109  } else {
110  rz_strbuf_appendf(sb, " {\n");
111  decode_buffer(sb, ps, pe, padcnt + 1, debug);
112  pad(sb, padcnt);
113  rz_strbuf_appendf(sb, "}\n");
114  }
115  bytes_read += var64;
116  } else {
117  eprintf("\ninvalid delimited length (%" PFMT64u ").\n", var64);
118  return;
119  }
120  } break;
121  case WIRE_START_GRP:
122  rz_strbuf_appendf(sb, " {\n");
123  padcnt++;
124  break;
125  case WIRE_END_GRP:
126  if (padcnt > 1) {
127  padcnt--;
128  }
129  pad(sb, padcnt);
130  rz_strbuf_appendf(sb, "}\n");
131  break;
132  case WIRE_32_BIT: {
133  ft32 *f = (ft32 *)&var32;
134  st32 *i = (st32 *)&var32;
135  bytes_read = read_u32_leb128(buffer, end, &var32);
136  rz_strbuf_appendf(sb, ": %u | %d | %f\n", var32, *i, *f);
137  } break;
138  default:
139  decode_array(sb, buffer - 1, end);
140  return;
141  }
142  buffer += bytes_read;
143  }
144 }
145 
146 RZ_API char *rz_protobuf_decode(const ut8 *start, const ut64 size, bool debug) {
147  if (!start || !size) {
148  eprintf("Invalid buffer pointer or size.\n");
149  return NULL;
150  }
151  const ut8 *end = start + size;
152  RzStrBuf *sb = rz_strbuf_new("");
153  decode_buffer(sb, start, end, 0u, debug);
154  return rz_strbuf_drain(sb);
155 }
lzma_index ** i
Definition: index.h:629
static SblHeader sb
Definition: bin_mbn.c:26
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
uint32_t ut32
voidpf void uLong size
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
RZ_API char * rz_protobuf_decode(const ut8 *start, const ut64 size, bool debug)
Definition: protobuf.c:146
static const char * s_wire(const ut8 byte)
Definition: protobuf.c:17
#define WIRE_VARINT
Definition: protobuf.c:10
static void pad(RzStrBuf *sb, ut32 count)
Definition: protobuf.c:36
double ft64
Definition: protobuf.c:8
static bool is_string(const ut8 *start, const ut8 *end)
Definition: protobuf.c:43
static void decode_buffer(RzStrBuf *sb, const ut8 *start, const ut8 *end, ut32 padcnt, bool debug)
Definition: protobuf.c:62
#define WIRE_64_BIT
Definition: protobuf.c:11
float ft32
Definition: protobuf.c:7
#define WIRE_END_GRP
Definition: protobuf.c:14
#define WIRE_START_GRP
Definition: protobuf.c:13
#define WIRE_LEN_DELIM
Definition: protobuf.c:12
static void decode_array(RzStrBuf *sb, const ut8 *start, const ut8 *end)
Definition: protobuf.c:54
#define WIRE_32_BIT
Definition: protobuf.c:15
#define eprintf(x, y...)
Definition: rlcc.c:7
#define IS_PRINTABLE(x)
Definition: rz_str_util.h:10
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
#define PFMT64d
Definition: rz_types.h:394
#define PFMT64u
Definition: rz_types.h:395
#define st64
Definition: rz_types_base.h:10
#define st32
Definition: rz_types_base.h:12
RZ_API size_t read_u64_leb128(const ut8 *p, const ut8 *max, ut64 *out_val)
Definition: uleb128.c:244
RZ_API size_t read_u32_leb128(const ut8 *p, const ut8 *max, ut32 *out_val)
Definition: uleb128.c:186
#define f(i)
Definition: sha256.c:46
Definition: buffer.h:15
static int debug
Definition: visual.c:21
ut64(WINAPI *w32_GetEnabledXStateFeatures)()