Skip to content

Commit 01f85af

Browse files
committed
Convert speakeasy/detect.c SHA256 and path buffers from heap to stack
compute_sha256_hex: Change from returning a g_malloc'd string to writing into a caller-provided buffer. SHA256 hex is always exactly 64 chars + null (65 bytes), making it ideal for a stack buffer. save_shellcode: Replace g_strdup_printf with snprintf into fixed stack buffers (SHELLCODE_PATH_MAX=512) for bin_path and txt_path. This eliminates 3 heap allocations and simplifies cleanup on every return path (no more g_free chains). https://claude.ai/code/session_01Pm9yPS4qqpBHtrvVYUSz7k
1 parent b54fd25 commit 01f85af

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

modules/speakeasy/detect.c

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,36 +48,44 @@ void speakeasy_set_shellcode_dir(const char *dir)
4848
shellcode_dir = g_strdup(dir);
4949
}
5050

51+
// SHA256 hex string is always 64 chars + null
52+
#define SHA256_HEX_SIZE 65
53+
// Max path: dir + "/shellcode-" + 64 hex chars + ".bin"/".txt" + null
54+
#define SHELLCODE_PATH_MAX 512
55+
5156
/**
52-
* Compute SHA256 hash of data and return as hex string
53-
* Caller must free the returned string with g_free()
57+
* Compute SHA256 hash of data and write hex string into caller-provided buffer
58+
* Buffer must be at least SHA256_HEX_SIZE (65) bytes
59+
* Returns true on success, false on failure
5460
*/
55-
static char *compute_sha256_hex(const void *data, size_t len)
61+
static bool compute_sha256_hex(char *hex, size_t hex_size, const void *data, size_t len)
5662
{
5763
unsigned char hash[EVP_MAX_MD_SIZE];
5864
unsigned int hash_len;
5965

66+
if (hex_size < SHA256_HEX_SIZE)
67+
return false;
68+
6069
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
6170
if (ctx == NULL) {
62-
return NULL;
71+
return false;
6372
}
6473

6574
if (EVP_DigestInit_ex(ctx, EVP_sha256(), NULL) != 1 ||
6675
EVP_DigestUpdate(ctx, data, len) != 1 ||
6776
EVP_DigestFinal_ex(ctx, hash, &hash_len) != 1) {
6877
EVP_MD_CTX_free(ctx);
69-
return NULL;
78+
return false;
7079
}
7180
EVP_MD_CTX_free(ctx);
7281

7382
// Convert to hex string
74-
char *hex = g_malloc(hash_len * 2 + 1);
7583
for (unsigned int i = 0; i < hash_len; i++) {
7684
snprintf(hex + i * 2, 3, "%02x", hash[i]);
7785
}
7886
hex[hash_len * 2] = '\0';
7987

80-
return hex;
88+
return true;
8189
}
8290

8391
/**
@@ -97,33 +105,37 @@ static bool save_shellcode(const void *data, size_t len, int offset,
97105
return false;
98106
}
99107

100-
char *sha256 = compute_sha256_hex(data, len);
101-
if (sha256 == NULL) {
108+
char sha256[SHA256_HEX_SIZE];
109+
if (!compute_sha256_hex(sha256, sizeof(sha256), data, len)) {
102110
g_warning("Failed to compute SHA256");
103111
return false;
104112
}
105113

106-
// Build file paths
107-
char *bin_path = g_strdup_printf("%s/shellcode-%s.bin", shellcode_dir, sha256);
108-
char *txt_path = g_strdup_printf("%s/shellcode-%s.txt", shellcode_dir, sha256);
114+
// Build file paths on stack
115+
char bin_path[SHELLCODE_PATH_MAX];
116+
char txt_path[SHELLCODE_PATH_MAX];
117+
int n = snprintf(bin_path, sizeof(bin_path), "%s/shellcode-%s.bin", shellcode_dir, sha256);
118+
if (n < 0 || (size_t)n >= sizeof(bin_path)) {
119+
g_warning("Shellcode bin path too long");
120+
return false;
121+
}
122+
n = snprintf(txt_path, sizeof(txt_path), "%s/shellcode-%s.txt", shellcode_dir, sha256);
123+
if (n < 0 || (size_t)n >= sizeof(txt_path)) {
124+
g_warning("Shellcode txt path too long");
125+
return false;
126+
}
109127

110128
// Check if already exists (dedup by hash)
111129
struct stat st;
112130
if (stat(bin_path, &st) == 0) {
113131
g_debug("Shellcode %s already saved", sha256);
114-
g_free(sha256);
115-
g_free(bin_path);
116-
g_free(txt_path);
117132
return true;
118133
}
119134

120135
// Save binary data
121136
FILE *f = fopen(bin_path, "wb");
122137
if (f == NULL) {
123138
g_warning("Failed to open %s for writing", bin_path);
124-
g_free(sha256);
125-
g_free(bin_path);
126-
g_free(txt_path);
127139
return false;
128140
}
129141
size_t written = fwrite(data, 1, len, f);
@@ -132,9 +144,6 @@ static bool save_shellcode(const void *data, size_t len, int offset,
132144
if (written != len) {
133145
g_warning("Failed to write shellcode data");
134146
unlink(bin_path);
135-
g_free(sha256);
136-
g_free(bin_path);
137-
g_free(txt_path);
138147
return false;
139148
}
140149

@@ -166,9 +175,6 @@ static bool save_shellcode(const void *data, size_t len, int offset,
166175

167176
g_info("Saved shellcode %s.bin (%zu bytes, %s)", sha256, len, arch);
168177

169-
g_free(sha256);
170-
g_free(bin_path);
171-
g_free(txt_path);
172178
return true;
173179
}
174180

0 commit comments

Comments
 (0)