Skip to content

Commit 6f7c8a3

Browse files
committed
ezlib_drv: avoid overflow when OOM
1 parent c14ef82 commit 6f7c8a3

File tree

2 files changed

+56
-12
lines changed

2 files changed

+56
-12
lines changed

c_src/ezlib_drv.c

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,45 @@ typedef struct {
3838
z_stream *i_stream;
3939
} ezlib_data;
4040

41+
/* Wrappers around driver_alloc() that check */
42+
/* for OOM. */
43+
#ifdef HAS_ERTS_EXIT
44+
void erts_exit(int n, char* v, ...);
45+
#define erl_exit erts_exit
46+
#else
47+
void erl_exit(int n, char* v, ...) { abort(); }
48+
#endif
49+
50+
void *ezlib_alloc(ErlDrvSizeT size);
51+
ErlDrvBinary *ezlib_alloc_binary(ErlDrvSizeT size);
52+
ErlDrvBinary *ezlib_realloc_binary(ErlDrvBinary *bin,
53+
ErlDrvSizeT size);
54+
55+
void *ezlib_alloc(ErlDrvSizeT size) {
56+
void *p = driver_alloc(size);
57+
if (p == NULL) {
58+
erl_exit(1, "ezlib: Can't allocate %lu bytes of memory\n",
59+
size);
60+
}
61+
return p;
62+
}
63+
64+
ErlDrvBinary *ezlib_alloc_binary(ErlDrvSizeT size) {
65+
ErlDrvBinary *p = driver_alloc_binary(size);
66+
if (p == NULL) {
67+
erl_exit(1, "ezlib: Can't allocate %lu binary\n", size);
68+
}
69+
return p;
70+
}
71+
72+
ErlDrvBinary *ezlib_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size) {
73+
ErlDrvBinary *p = driver_realloc_binary(bin, size);
74+
if (p == NULL) {
75+
erl_exit(1, "ezlib: Can't reallocate %lu binary\n", size);
76+
}
77+
return p;
78+
}
79+
4180
static void* zlib_alloc(void* data, unsigned int items, unsigned int size)
4281
{
4382
return (void*) driver_alloc(items*size);
@@ -51,18 +90,18 @@ static void zlib_free(void* data, void* addr)
5190
static ErlDrvData ezlib_drv_start(ErlDrvPort port, char *buff)
5291
{
5392
ezlib_data *d =
54-
(ezlib_data *)driver_alloc(sizeof(ezlib_data));
93+
ezlib_alloc(sizeof(ezlib_data));
5594
d->port = port;
5695

57-
d->d_stream = (z_stream *)driver_alloc(sizeof(z_stream));
96+
d->d_stream = ezlib_alloc(sizeof(z_stream));
5897

5998
d->d_stream->zalloc = zlib_alloc;
6099
d->d_stream->zfree = zlib_free;
61100
d->d_stream->opaque = (voidpf)0;
62101

63102
deflateInit(d->d_stream, Z_DEFAULT_COMPRESSION);
64103

65-
d->i_stream = (z_stream *)driver_alloc(sizeof(z_stream));
104+
d->i_stream = ezlib_alloc(sizeof(z_stream));
66105

67106
d->i_stream->zalloc = zlib_alloc;
68107
d->i_stream->zfree = zlib_free;
@@ -96,7 +135,7 @@ static void ezlib_drv_stop(ErlDrvData handle)
96135
if (!(cond)) \
97136
{ \
98137
rlen = strlen(errstr) + 1; \
99-
b = driver_realloc_binary(b, rlen); \
138+
b = ezlib_realloc_binary(b, rlen); \
100139
b->orig_bytes[0] = 1; \
101140
strncpy(b->orig_bytes + 1, errstr, rlen - 1); \
102141
*rbuf = (char *)b; \
@@ -119,7 +158,7 @@ static ErlDrvSSizeT ezlib_drv_control(ErlDrvData handle,
119158
case DEFLATE:
120159
size = BUF_SIZE + 1;
121160
rlen = 1;
122-
b = driver_alloc_binary(size);
161+
b = ezlib_alloc_binary(size);
123162
b->orig_bytes[0] = 0;
124163

125164
d->d_stream->next_in = (unsigned char *)buf;
@@ -145,15 +184,15 @@ static ErlDrvSSizeT ezlib_drv_control(ErlDrvData handle,
145184

146185
rlen += (BUF_SIZE - d->d_stream->avail_out);
147186
size += (BUF_SIZE - d->d_stream->avail_out);
148-
b = driver_realloc_binary(b, size);
187+
b = ezlib_realloc_binary(b, size);
149188
}
150-
b = driver_realloc_binary(b, rlen);
189+
b = ezlib_realloc_binary(b, rlen);
151190
*rbuf = (char *)b;
152191
return rlen;
153192
case INFLATE:
154193
size = BUF_SIZE + 1;
155194
rlen = 1;
156-
b = driver_alloc_binary(size);
195+
b = ezlib_alloc_binary(size);
157196
b->orig_bytes[0] = 0;
158197

159198
if (len > 0) {
@@ -180,15 +219,15 @@ static ErlDrvSSizeT ezlib_drv_control(ErlDrvData handle,
180219

181220
rlen += (BUF_SIZE - d->i_stream->avail_out);
182221
size += (BUF_SIZE - d->i_stream->avail_out);
183-
b = driver_realloc_binary(b, size);
222+
b = ezlib_realloc_binary(b, size);
184223
}
185224
}
186-
b = driver_realloc_binary(b, rlen);
225+
b = ezlib_realloc_binary(b, rlen);
187226
*rbuf = (char *)b;
188227
return rlen;
189228
}
190229

191-
b = driver_alloc_binary(1);
230+
b = ezlib_alloc_binary(1);
192231
b->orig_bytes[0] = 0;
193232
*rbuf = (char *)b;
194233
return 1;

rebar.config.script

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ ModCfg0 = fun(F, Cfg, [Key|Tail], Op, Default) ->
4646
ModCfg = fun(Cfg, Keys, Op, Default) -> ModCfg0(ModCfg0, Cfg, Keys, Op, Default) end.
4747
ModCfgS = fun(Cfg, Keys, Val) -> ModCfg0(ModCfg0, Cfg, Keys, fun(_V) -> Val end, "") end.
4848

49-
Cfg0 = ModCfg(CONFIG, [port_env, "CFLAGS"], fun(V) -> V ++ " " ++ CfgCFlags end, "$CFLAGS"),
49+
SysVersion = lists:map(fun erlang:list_to_integer/1,
50+
string:tokens(erlang:system_info(version), ".")),
51+
52+
ExitFlag = case SysVersion >= [7, 3] of true -> "-DHAS_ERTS_EXIT"; _ -> "" end.
53+
54+
Cfg0 = ModCfg(CONFIG, [port_env, "CFLAGS"], fun(V) -> V ++ " " ++ ExitFlag ++ " " ++ CfgCFlags end, "$CFLAGS"),
5055
Cfg00 = ModCfg(Cfg0, [port_env, "LDFLAGS"], fun(V) -> V ++ " " ++ CfgLDFlags end, "$LDFLAGS"),
5156
Cfg1 = case CfgWithGCov of
5257
"true" ->

0 commit comments

Comments
 (0)