Skip to content

Commit a739923

Browse files
Grond66Samuel ArnoldRot127
authored
Fix unchecked allocations (#2844)
* Fix trivial unchecked allocations * Move instruction lookup caching allocation into the core * Apply formatting nitpicks Co-authored-by: Rot127 <45763064+Rot127@users.noreply.github.com> * Assert to avoid an integer overflow in lookup_insn_map() * Remove unused member from cs_struct * Document what happens when lookup_insn_map() fails --------- Co-authored-by: Samuel Arnold <samuel.arnold@crowdstrike.com> Co-authored-by: Rot127 <45763064+Rot127@users.noreply.github.com>
1 parent 6705cb8 commit a739923

28 files changed

+255
-140
lines changed

Mapping.c

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,53 @@
77
#include "cs_priv.h"
88
#include "utils.h"
99

10-
// create a cache for fast id lookup
11-
static unsigned short *make_id2insn(const insn_map *insns, unsigned int size)
10+
// Create a cache to map LLVM instruction IDs to capstone instruction IDs, if
11+
// the architecture needs this.
12+
cs_err populate_insn_map_cache(cs_struct *handle)
1213
{
13-
// NOTE: assume that the max id is always put at the end of insns array
14-
unsigned short max_id = insns[size - 1].id;
1514
unsigned int i;
1615

17-
unsigned short *cache =
18-
(unsigned short *)cs_mem_calloc(max_id + 1, sizeof(*cache));
16+
// If this architecture doesn't use instruction mapping, do nothing
17+
if (!handle->insn_map || handle->insn_map_size <= 0)
18+
return CS_ERR_OK;
1919

20-
for (i = 1; i < size; i++)
21-
cache[insns[i].id] = i;
20+
// Since the instruction map is assumed to be stored in ascending
21+
// order, we can get the maximum LLVM instruction id just by looking at
22+
// the last element.
23+
unsigned int cache_elements =
24+
handle->insn_map[handle->insn_map_size - 1].id + 1;
2225

23-
return cache;
26+
// This should not be initialized yet.
27+
CS_ASSERT(!handle->insn_cache);
28+
29+
unsigned short *cache = cs_mem_calloc(cache_elements, sizeof(*cache));
30+
if (!cache) {
31+
handle->errnum = CS_ERR_MEM;
32+
return CS_ERR_MEM;
33+
}
34+
handle->insn_cache = cache;
35+
36+
for (i = 1; i < handle->insn_map_size; ++i)
37+
handle->insn_cache[handle->insn_map[i].id] = i;
38+
39+
return CS_ERR_OK;
2440
}
2541

26-
// look for @id in @insns, given its size in @max. first time call will update
27-
// @cache. return 0 if not found
28-
unsigned short insn_find(const insn_map *insns, unsigned int max,
29-
unsigned int id, unsigned short **cache)
42+
const insn_map *lookup_insn_map(cs_struct *handle, unsigned short id)
3043
{
31-
if (id > insns[max - 1].id)
32-
return 0;
44+
// If this is getting called, we need the cache to already be populated
45+
// (this should be done when populate_insn_map_cache() gets called).
46+
CS_ASSERT(handle->insn_cache);
47+
CS_ASSERT(handle->insn_map_size);
48+
49+
unsigned short highest_id =
50+
handle->insn_map[handle->insn_map_size - 1].id;
51+
if (id > highest_id)
52+
return NULL;
3353

34-
if (*cache == NULL)
35-
*cache = make_id2insn(insns, max);
54+
unsigned short i = handle->insn_cache[id];
3655

37-
return (*cache)[id];
56+
return &handle->insn_map[i];
3857
}
3958

4059
// Gives the id for the given @name if it is saved in @map.

Mapping.h

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,16 @@
1515
#include <assert.h>
1616
#include <string.h>
1717

18-
// map instruction to its characteristics
19-
typedef struct insn_map {
20-
unsigned short id; // The LLVM instruction id
21-
unsigned short mapid; // The Capstone instruction id
22-
#ifndef CAPSTONE_DIET
23-
uint16_t regs_use[MAX_IMPL_R_REGS]; ///< list of implicit registers used by
24-
///< this instruction
25-
uint16_t regs_mod[MAX_IMPL_W_REGS]; ///< list of implicit registers modified
26-
///< by this instruction
27-
unsigned char groups
28-
[MAX_NUM_GROUPS]; ///< list of group this instruction belong to
29-
bool branch; // branch instruction?
30-
bool indirect_branch; // indirect branch instruction?
31-
union {
32-
ppc_suppl_info ppc;
33-
loongarch_suppl_info loongarch;
34-
aarch64_suppl_info aarch64;
35-
systemz_suppl_info systemz;
36-
arm_suppl_info arm;
37-
xtensa_suppl_info xtensa;
38-
sparc_suppl_info sparc;
39-
} suppl_info; // Supplementary information for each instruction.
40-
#endif
41-
} insn_map;
42-
43-
// look for @id in @m, given its size in @max. first time call will update
44-
// @cache. return 0 if not found
45-
unsigned short insn_find(const insn_map *m, unsigned int max, unsigned int id,
46-
unsigned short **cache);
18+
// Create a cache to map LLVM instruction IDs to capstone instruction IDs, if
19+
// the architecture needs this.
20+
cs_err populate_insn_map_cache(cs_struct *handle);
21+
22+
// Lookup the insn_map instance for an LLVM instruction ID. This method assumes
23+
// that this architecture uses the instruction mapping functionality available
24+
// from populate_insn_map_cache().
25+
// Returns NULL in case id is larger than the maximum mapped LLVM instruction
26+
// ID.
27+
const insn_map *lookup_insn_map(cs_struct *handle, unsigned short id);
4728

4829
unsigned int find_cs_id(unsigned MC_Opcode, const insn_map *imap,
4930
unsigned imap_size);

arch/AArch64/AArch64Module.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ cs_err AArch64_global_init(cs_struct *ud)
1313
{
1414
MCRegisterInfo *mri;
1515
mri = cs_mem_malloc(sizeof(*mri));
16+
if (!mri)
17+
return CS_ERR_MEM;
1618

1719
AArch64_init_mri(mri);
1820
ud->printer = AArch64_printer;

arch/ARC/ARCModule.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ cs_err ARC_global_init(cs_struct *ud)
1414
{
1515
MCRegisterInfo *mri;
1616
mri = cs_mem_malloc(sizeof(*mri));
17+
if (!mri)
18+
return CS_ERR_MEM;
1719

1820
ARC_init_mri(mri);
1921

@@ -49,4 +51,4 @@ cs_err ARC_option(cs_struct *handle, cs_opt_type type, size_t value)
4951
return CS_ERR_OK;
5052
}
5153

52-
#endif
54+
#endif

arch/ARM/ARMModule.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ cs_err ARM_global_init(cs_struct *ud)
1414
{
1515
MCRegisterInfo *mri;
1616
mri = cs_mem_malloc(sizeof(*mri));
17+
if (!mri)
18+
return CS_ERR_MEM;
1719

1820
ARM_init_mri(mri);
1921

arch/Alpha/AlphaMapping.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ static const insn_map insns[] = {
2323
#include "AlphaGenCSMappingInsn.inc"
2424
};
2525

26+
const insn_map *Alpha_insns = insns;
27+
const unsigned int Alpha_insn_count = ARR_SIZE(insns);
28+
2629
static const map_insn_ops insn_operands[] = {
2730
#include "AlphaGenCSMappingInsnOp.inc"
2831
};
@@ -81,30 +84,28 @@ void Alpha_set_detail_op_reg(MCInst *MI, unsigned OpNum, alpha_op_type Reg)
8184
// given internal insn id, return public instruction info
8285
void Alpha_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
8386
{
84-
unsigned short i;
87+
insn_map const *insn_map = NULL;
8588

86-
i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
87-
if (i == 0) {
89+
if (!(insn_map = lookup_insn_map(h, id)))
8890
return;
89-
}
90-
insn->id = insns[i].mapid;
91+
insn->id = insn_map->mapid;
9192

9293
if (insn->detail) {
9394
#ifndef CAPSTONE_DIET
94-
memcpy(insn->detail->regs_read, insns[i].regs_use,
95-
sizeof(insns[i].regs_use));
95+
memcpy(insn->detail->regs_read, insn_map->regs_use,
96+
sizeof(insn_map->regs_use));
9697
insn->detail->regs_read_count =
97-
(uint8_t)count_positive(insns[i].regs_use);
98+
(uint8_t)count_positive(insn_map->regs_use);
9899

99-
memcpy(insn->detail->regs_write, insns[i].regs_mod,
100-
sizeof(insns[i].regs_mod));
100+
memcpy(insn->detail->regs_write, insn_map->regs_mod,
101+
sizeof(insn_map->regs_mod));
101102
insn->detail->regs_write_count =
102-
(uint8_t)count_positive(insns[i].regs_mod);
103+
(uint8_t)count_positive(insn_map->regs_mod);
103104

104-
memcpy(insn->detail->groups, insns[i].groups,
105-
sizeof(insns[i].groups));
105+
memcpy(insn->detail->groups, insn_map->groups,
106+
sizeof(insn_map->groups));
106107
insn->detail->groups_count =
107-
(uint8_t)count_positive8(insns[i].groups);
108+
(uint8_t)count_positive8(insn_map->groups);
108109
#endif
109110
}
110111
}

arch/Alpha/AlphaMapping.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
// unsigned int Alpha_map_insn_id(cs_struct *h, unsigned int id);
1313

14+
extern const insn_map *Alpha_insns;
15+
extern const unsigned int Alpha_insn_count;
16+
1417
// given internal insn id, return public instruction info
1518
void Alpha_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
1619

arch/Alpha/AlphaModule.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ cs_err ALPHA_global_init(cs_struct *ud)
1414
MCRegisterInfo *mri;
1515

1616
mri = cs_mem_malloc(sizeof(*mri));
17+
if (!mri)
18+
return CS_ERR_MEM;
1719

1820
Alpha_init(mri);
1921
ud->printer = Alpha_printInst;
@@ -29,6 +31,8 @@ cs_err ALPHA_global_init(cs_struct *ud)
2931
#ifndef CAPSTONE_DIET
3032
ud->reg_access = Alpha_reg_access;
3133
#endif
34+
ud->insn_map = Alpha_insns;
35+
ud->insn_map_size = Alpha_insn_count;
3236

3337
return CS_ERR_OK;
3438
}

arch/LoongArch/LoongArchModule.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ cs_err LoongArch_global_init(cs_struct *ud)
1515
{
1616
MCRegisterInfo *mri;
1717
mri = cs_mem_malloc(sizeof(*mri));
18+
if (!mri)
19+
return CS_ERR_MEM;
1820

1921
LoongArch_init_mri(mri);
2022

arch/MOS65XX/MOS65XXModule.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ cs_err MOS65XX_global_init(cs_struct *ud)
1414
mos65xx_info *info;
1515

1616
info = cs_mem_malloc(sizeof(*info));
17+
if (!info)
18+
return CS_ERR_MEM;
19+
1720
info->hex_prefix = NULL;
1821
info->cpu_type = MOS65XX_CPU_TYPE_6502;
1922
info->long_m = 0;

0 commit comments

Comments
 (0)