Rizin
unix-like reverse engineering framework and cli tools
class_attribute.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "class_attribute.h"
5 
7  ut8 *buffer;
10  return NULL;
11  }
12 
13  buffer = (ut8 *)malloc(size + 1);
14  if (!buffer || rz_buf_read(buf, buffer, size) < (size - 1)) {
16  free(buffer);
17  return NULL;
18  }
19  buffer[size] = 0;
20 
21  return buffer;
22 }
23 
24 static char *resolve_const_pool_index(ConstPool **pool, ut32 poolsize, ut32 index) {
25  const ConstPool *cpool;
26  if (index >= poolsize || !(cpool = pool[index])) {
27  return NULL;
28  }
29  return java_constant_pool_stringify(cpool);
30 }
31 
34  if (attr->attribute_length < 1) {
35  return true;
36  }
37  st64 size = (st64)attr->attribute_length;
39  return true;
40 }
41 
45  if (!acv) {
47  return false;
48  }
49 
50  if (!rz_buf_read_be16(buf, &acv->index)) {
51  free(acv);
52  return false;
53  }
54 
56  attr->info = (void *)acv;
57  return true;
58 }
59 
60 bool java_attribute_set_code(ConstPool **pool, ut32 poolsize, Attribute *attr, RzBuffer *buf, bool is_oak) {
62  if (!ac) {
64  return false;
65  }
66 
67  if (is_oak) {
68  ut8 max_stack;
69  if (!rz_buf_read8(buf, &max_stack)) {
70  free(ac);
71  return false;
72  }
73  ac->max_stack = max_stack;
74 
75  ut8 max_locals;
76  if (!rz_buf_read8(buf, &max_locals)) {
77  free(ac);
78  return false;
79  }
80  ac->max_locals = max_locals;
81 
82  ut16 code_length;
83  if (!rz_buf_read_be16(buf, &code_length)) {
84  free(ac);
85  return false;
86  }
87  ac->code_length = code_length;
88  } else {
89  if (!rz_buf_read_be16(buf, &ac->max_stack) ||
92  free(ac);
93  return false;
94  }
95  }
96 
97  ac->code_offset = attr->offset + (is_oak ? 10 : 14); // 6 bytes for attribute + 8 as code
100  free(ac);
101  return false;
102  }
103 
104  if (ac->exceptions_count > 0) {
106  if (!ac->exceptions) {
107  free(ac);
109  return false;
110  }
111 
112  for (ut32 i = 0; i < ac->exceptions_count; ++i) {
113  if (!rz_buf_read_be16(buf, &ac->exceptions[i].start_pc) ||
117  free(ac);
118  return false;
119  }
120  }
121  }
122 
123  if (!rz_buf_read_be16(buf, &ac->attributes_count)) {
124  free(ac->exceptions);
125  free(ac);
126  return false;
127  }
128 
129  if (ac->attributes_count > 0) {
131  if (!ac->attributes) {
132  free(ac->exceptions);
133  free(ac);
135  return false;
136  }
137 
138  for (ut32 i = 0; i < ac->attributes_count; ++i) {
140  if (attr && java_attribute_resolve(pool, poolsize, attr, buf, false)) {
141  ac->attributes[i] = attr;
142  } else {
143  java_attribute_free(attr);
144  break;
145  }
146  }
147  }
148 
149  attr->type = ATTRIBUTE_TYPE_CODE;
150  attr->info = (void *)ac;
151  return true;
152 }
153 
155  rz_warn_if_fail(attr->attribute_length == 2);
157  if (!asf) {
159  return false;
160  }
161  if (!rz_buf_read_be16(buf, &asf->index)) {
162  free(asf);
163  return false;
164  }
165 
167  attr->info = (void *)asf;
168  return true;
169 }
170 
173  if (attr->attribute_length < 1) {
174  return true;
175  }
176  st64 size = (st64)attr->attribute_length;
177  /*
178  The debug_extension array holds a string, which must be in UTF-8 format. There is no terminating zero byte.
179  The string in the debug_extension item will be interpreted as extended debugging information.
180  */
181  attr->info = make_string(buf, size);
182  if (!attr->info) {
184  return false;
185  }
186  return true;
187 }
188 
190  rz_warn_if_fail(attr->attribute_length >= 2);
192  if (!alnt) {
194  return false;
195  }
196  if (!rz_buf_read_be16(buf, &alnt->table_length)) {
197  free(alnt);
198  return false;
199  }
200  if (alnt->table_length > 0) {
201  alnt->table = RZ_NEWS0(LineNumberTable, alnt->table_length);
202  if (!alnt->table) {
203  free(alnt);
205  return false;
206  }
207  for (ut32 i = 0; i < alnt->table_length; ++i) {
208  if (!rz_buf_read_be16(buf, &alnt->table[i].start_pc) ||
209  !rz_buf_read_be16(buf, &alnt->table[i].line_number)) {
210  free(alnt->table);
211  free(alnt);
212  return false;
213  }
214  }
215  }
216 
218  attr->info = (void *)alnt;
219  return true;
220 }
221 
223  rz_warn_if_fail(attr->attribute_length >= 2);
225  if (!alvt) {
227  return false;
228  }
229  if (!rz_buf_read_be16(buf, &alvt->table_length)) {
230  free(alvt);
231  return false;
232  }
233  if (alvt->table_length > 0) {
235  if (!alvt->table) {
236  free(alvt);
238  return false;
239  }
240  for (ut32 i = 0; i < alvt->table_length; ++i) {
241  if (!rz_buf_read_be16(buf, &alvt->table[i].start_pc) ||
242  !rz_buf_read_be16(buf, &alvt->table[i].length) ||
243  !rz_buf_read_be16(buf, &alvt->table[i].name_index) ||
245  !rz_buf_read_be16(buf, &alvt->table[i].index)) {
246  free(alvt->table);
247  free(alvt);
248  return false;
249  }
250  }
251  }
252 
254  attr->info = (void *)alvt;
255  return true;
256 }
257 
259  rz_warn_if_fail(attr->attribute_length >= 2);
261  if (!alvtt) {
263  return false;
264  }
265  if (!rz_buf_read_be16(buf, &alvtt->table_length)) {
266  free(alvtt);
267  return false;
268  }
269  if (alvtt->table_length > 0) {
271  if (!alvtt->table) {
272  free(alvtt);
274  return false;
275  }
276  for (ut32 i = 0; i < alvtt->table_length; ++i) {
277  if (!rz_buf_read_be16(buf, &alvtt->table[i].start_pc) ||
278  !rz_buf_read_be16(buf, &alvtt->table[i].length) ||
279  !rz_buf_read_be16(buf, &alvtt->table[i].name_index) ||
281  !rz_buf_read_be16(buf, &alvtt->table[i].index)) {
282  free(alvtt->table);
283  free(alvtt);
284  return false;
285  }
286  }
287  }
288 
290  attr->info = (void *)alvtt;
291  return true;
292 }
293 
295  rz_warn_if_fail(attr->attribute_length >= 16);
297  if (!am) {
299  return false;
300  }
301  ut16 *tmp16 = NULL;
302  if (!rz_buf_read_be16(buf, &am->module_name_index) ||
305  goto java_attribute_set_module_bad;
306  return false;
307  }
308 
309  if (!rz_buf_read_be16(buf, &am->requires_count)) {
310  goto java_attribute_set_module_bad;
311  }
312 
313  if (am->requires_count > 0) {
315  if (!am->requires) {
316  goto java_attribute_set_module_bad;
317  }
318  for (ut32 i = 0; i < am->requires_count; ++i) {
319  if (!rz_buf_read_be16(buf, &am->requires[i].index) ||
320  !rz_buf_read_be16(buf, &am->requires[i].flags) ||
322  goto java_attribute_set_module_bad;
323  }
324  }
325  }
326 
327  if (!rz_buf_read_be16(buf, &am->exports_count)) {
328  goto java_attribute_set_module_bad;
329  }
330 
331  if (am->exports_count > 0) {
333  if (!am->exports) {
334  goto java_attribute_set_module_bad;
335  }
336  for (ut32 i = 0; i < am->exports_count; ++i) {
337  if (!rz_buf_read_be16(buf, &am->exports[i].index) ||
338  !rz_buf_read_be16(buf, &am->exports[i].flags) ||
340  goto java_attribute_set_module_bad;
341  }
342  tmp16 = RZ_NEWS0(ut16, am->exports[i].to_count);
343  if (!tmp16) {
344  goto java_attribute_set_module_bad;
345  }
346  am->exports[i].to_indices = tmp16;
347  for (ut32 k = 0; k < am->exports[i].to_count; ++k) {
348  if (!rz_buf_read_be16(buf, &tmp16[k])) {
349  goto java_attribute_set_module_bad;
350  }
351  }
352  }
353  }
354 
355  if (!rz_buf_read_be16(buf, &am->opens_count)) {
356  goto java_attribute_set_module_bad;
357  }
358 
359  if (am->opens_count > 0) {
360  am->opens = RZ_NEWS0(ModuleOpen, am->opens_count);
361  if (!am->opens) {
362  goto java_attribute_set_module_bad;
363  }
364  for (ut32 i = 0; i < am->opens_count; ++i) {
365  if (!rz_buf_read_be16(buf, &am->opens[i].index) ||
366  !rz_buf_read_be16(buf, &am->opens[i].flags) ||
367  !rz_buf_read_be16(buf, &am->opens[i].to_count)) {
368  goto java_attribute_set_module_bad;
369  }
370  tmp16 = RZ_NEWS0(ut16, am->opens[i].to_count);
371  if (!tmp16) {
372  goto java_attribute_set_module_bad;
373  }
374  am->opens[i].to_indices = tmp16;
375  for (ut32 k = 0; k < am->opens[i].to_count; ++k) {
376  if (!rz_buf_read_be16(buf, &tmp16[k])) {
377  goto java_attribute_set_module_bad;
378  }
379  }
380  }
381  }
382 
383  if (!rz_buf_read_be16(buf, &am->uses_count)) {
384  goto java_attribute_set_module_bad;
385  }
386 
387  if (am->uses_count > 0) {
388  tmp16 = RZ_NEWS0(ut16, am->uses_count);
389  if (!tmp16) {
390  goto java_attribute_set_module_bad;
391  }
392  am->uses_index = tmp16;
393  for (ut32 i = 0; i < am->uses_count; ++i) {
394  if (!rz_buf_read_be16(buf, &tmp16[i])) {
395  goto java_attribute_set_module_bad;
396  }
397  }
398  }
399 
400  if (!rz_buf_read_be16(buf, &am->provides_count)) {
401  goto java_attribute_set_module_bad;
402  }
403 
404  if (am->provides_count > 0) {
406  if (!am->provides) {
407  goto java_attribute_set_module_bad;
408  }
409  for (ut32 i = 0; i < am->provides_count; ++i) {
410  if (!rz_buf_read_be16(buf, &am->provides[i].index) ||
412  goto java_attribute_set_module_bad;
413  }
414  tmp16 = RZ_NEWS0(ut16, am->provides[i].with_count);
415  if (!tmp16) {
416  goto java_attribute_set_module_bad;
417  }
418  am->provides[i].with_indices = tmp16;
419  for (ut32 k = 0; k < am->provides[i].with_count; ++k) {
420  if (!rz_buf_read_be16(buf, &tmp16[k])) {
421  goto java_attribute_set_module_bad;
422  }
423  }
424  }
425  }
426 
427  attr->type = ATTRIBUTE_TYPE_MODULE;
428  attr->info = (void *)am;
429  return true;
430 
431 java_attribute_set_module_bad:
432  if (am->exports) {
433  for (ut32 i = 0; i < am->exports_count; ++i) {
434  free(am->exports[i].to_indices);
435  }
436  }
437  if (am->opens) {
438  for (ut32 i = 0; i < am->opens_count; ++i) {
439  free(am->opens[i].to_indices);
440  }
441  }
442  if (am->provides) {
443  for (ut32 i = 0; i < am->provides_count; ++i) {
444  free(am->provides[i].with_indices);
445  }
446  }
447  free(am->uses_index);
448  free(am->exports);
449  free(am->requires);
450  free(am);
451  return false;
452 }
453 
455  rz_warn_if_fail(attr->attribute_length >= 2);
457  if (!amp) {
459  return false;
460  }
461 
462  if (!rz_buf_read_be16(buf, &amp->package_count)) {
463  free(amp);
464  return false;
465  }
466 
467  if (amp->package_count > 0) {
469  if (!amp->package_index) {
470  free(amp);
472  return false;
473  }
474  for (ut32 k = 0; k < amp->package_count; ++k) {
475  if (!rz_buf_read_be16(buf, &amp->package_index[k])) {
476  free(amp->package_index);
477  free(amp);
478  return false;
479  }
480  }
481  }
482 
484  attr->info = (void *)amp;
485  return true;
486 }
487 
489  rz_warn_if_fail(attr->attribute_length == 2);
491  if (!ammc) {
493  return false;
494  }
495  if (!rz_buf_read_be16(buf, &ammc->main_class_index)) {
496  free(ammc);
497  return false;
498  }
500  attr->info = (void *)ammc;
501  return true;
502 }
503 
504 bool java_attribute_resolve(ConstPool **pool, ut32 poolsize, Attribute *attr, RzBuffer *buf, bool is_oak) {
505  char *name = resolve_const_pool_index(pool, poolsize, attr->attribute_name_index);
506  if (!name) {
507  return false;
508  }
509 
510  bool result = false;
511  if (!strcmp(name, "ConstantValue")) {
512  result = java_attribute_set_constantvalue(attr, buf);
513  } else if (!strcmp(name, "Code")) {
514  result = java_attribute_set_code(pool, poolsize, attr, buf, is_oak);
515  } else if (!strcmp(name, "SourceFile")) {
516  result = java_attribute_set_sourcefile(attr, buf);
517  } else if (!strcmp(name, "SourceDebugExtension")) {
519  } else if (!strcmp(name, "LineNumberTable")) {
520  result = java_attribute_set_linenumbertable(attr, buf);
521  } else if (!strcmp(name, "LocalVariableTable")) {
523  } else if (!strcmp(name, "LocalVariableTypeTable")) {
525  } else if (!strcmp(name, "Module")) {
526  result = java_attribute_set_module(attr, buf);
527  } else if (!strcmp(name, "ModulePackages")) {
528  result = java_attribute_set_modulepackages(attr, buf);
529  } else if (!strcmp(name, "ModuleMainClass")) {
530  result = java_attribute_set_modulemainclass(attr, buf);
531  }
532 
533  if (!result) {
534  result = java_attribute_set_unknown(attr, buf);
535  }
536  free(name);
537  return result;
538 }
539 
541  Attribute *attr = RZ_NEW0(Attribute);
543 
544  attr->offset = offset;
545 
546  if (!rz_buf_read_be16(buf, &attr->attribute_name_index)) {
547  free(attr);
548  return NULL;
549  }
550 
551  if (!rz_buf_read_be32(buf, &attr->attribute_length)) {
552  free(attr);
553  return NULL;
554  }
555 
556  return attr;
557 }
558 
560  if (!attr || !attr->info) {
561  free(attr);
562  return;
563  }
564  if (attr->type == ATTRIBUTE_TYPE_CODE) {
565  AttributeCode *ac = (AttributeCode *)attr->info;
566  free(ac->exceptions);
567  if (ac->attributes) {
568  for (ut32 i = 0; i < ac->attributes_count; ++i) {
570  }
571  free(ac->attributes);
572  }
573  } else if (attr->type == ATTRIBUTE_TYPE_LINENUMBERTABLE) {
575  free(alnt->table);
576  } else if (attr->type == ATTRIBUTE_TYPE_LOCALVARIABLETABLE) {
578  free(alvt->table);
579  } else if (attr->type == ATTRIBUTE_TYPE_MODULE) {
580  AttributeModule *am = (AttributeModule *)attr->info;
581  for (ut32 i = 0; i < am->exports_count; ++i) {
582  free(am->exports[i].to_indices);
583  }
584  for (ut32 i = 0; i < am->opens_count; ++i) {
585  free(am->opens[i].to_indices);
586  }
587  for (ut32 i = 0; i < am->provides_count; ++i) {
588  free(am->provides[i].with_indices);
589  }
590  free(am->uses_index);
591  free(am->exports);
592  free(am->requires);
593  } else if (attr->type == ATTRIBUTE_TYPE_MODULEPACKAGES) {
595  free(amp->package_index);
596  }
597  free(attr->info);
598  free(attr);
599 }
lzma_index ** i
Definition: index.h:629
struct buffer buffer
bool java_attribute_set_sourcefile(Attribute *attr, RzBuffer *buf)
bool java_attribute_set_localvariabletypetable(Attribute *attr, RzBuffer *buf)
bool java_attribute_resolve(ConstPool **pool, ut32 poolsize, Attribute *attr, RzBuffer *buf, bool is_oak)
bool java_attribute_set_modulemainclass(Attribute *attr, RzBuffer *buf)
bool java_attribute_set_module(Attribute *attr, RzBuffer *buf)
bool java_attribute_set_sourcedebugextension(Attribute *attr, RzBuffer *buf)
bool java_attribute_set_modulepackages(Attribute *attr, RzBuffer *buf)
bool java_attribute_set_localvariabletable(Attribute *attr, RzBuffer *buf)
Attribute * java_attribute_new(RzBuffer *buf, ut64 offset)
void java_attribute_free(Attribute *attr)
static ut8 * make_string(RzBuffer *buf, st64 size)
static char * resolve_const_pool_index(ConstPool **pool, ut32 poolsize, ut32 index)
bool java_attribute_set_code(ConstPool **pool, ut32 poolsize, Attribute *attr, RzBuffer *buf, bool is_oak)
bool java_attribute_set_linenumbertable(Attribute *attr, RzBuffer *buf)
bool java_attribute_set_unknown(Attribute *attr, RzBuffer *buf)
bool java_attribute_set_constantvalue(Attribute *attr, RzBuffer *buf)
@ ATTRIBUTE_TYPE_MODULEMAINCLASS
@ ATTRIBUTE_TYPE_CODE
@ ATTRIBUTE_TYPE_SOURCEFILE
@ ATTRIBUTE_TYPE_MODULEPACKAGES
@ ATTRIBUTE_TYPE_LOCALVARIABLETYPETABLE
@ ATTRIBUTE_TYPE_MODULE
@ ATTRIBUTE_TYPE_LOCALVARIABLETABLE
@ ATTRIBUTE_TYPE_CONSTANTVALUE
@ ATTRIBUTE_TYPE_UNKNOWN
@ ATTRIBUTE_TYPE_LINENUMBERTABLE
@ ATTRIBUTE_TYPE_SOURCEDEBUGEXTENSION
char * java_constant_pool_stringify(const ConstPool *cpool)
#define NULL
Definition: cris-opc.c:27
uint16_t ut16
uint32_t ut32
const char * k
Definition: dsignal.c:11
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * malloc(size_t size)
Definition: malloc.c:123
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_warn_if_fail(expr)
Definition: rz_assert.h:35
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API st64 rz_buf_seek(RZ_NONNULL RzBuffer *b, st64 addr, int whence)
Modify the current cursor position in the buffer.
Definition: buf.c:1166
#define RZ_BUF_CUR
Definition: rz_buf.h:15
#define rz_buf_read_be16(b, result)
Definition: rz_buf.h:280
#define rz_buf_read_be32(b, result)
Definition: rz_buf.h:281
RZ_API bool rz_buf_read8(RZ_NONNULL RzBuffer *b, RZ_NONNULL RZ_OUT ut8 *result)
Read a byte at the cursor in the buffer.
Definition: buf.c:860
RZ_API st64 rz_buf_read(RZ_NONNULL RzBuffer *b, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define st64
Definition: rz_types_base.h:10
#define UT64_MAX
Definition: rz_types_base.h:86
Definition: buffer.h:15
ExceptionTable * exceptions
ModuleProvide * provides
ModuleRequire * requires
AttributeType type
Definition: z80asm.h:102
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
#define buffer_size(buffer)