aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/erl_bif_port.c
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2010-03-24 19:57:07 +0100
committerBjörn Gustavsson <[email protected]>2010-03-29 13:52:46 +0200
commit80ce0ac4458c549fd0969333dfbbf8b3233cf544 (patch)
tree9d5d8ff2662ff70f51b99f03af91fa6c06cee62c /erts/emulator/beam/erl_bif_port.c
parent985d201454d0cb43d5ed3230d6afeaeea0a1fe2c (diff)
downloadotp-80ce0ac4458c549fd0969333dfbbf8b3233cf544.tar.gz
otp-80ce0ac4458c549fd0969333dfbbf8b3233cf544.tar.bz2
otp-80ce0ac4458c549fd0969333dfbbf8b3233cf544.zip
Fix erlang:decode_packet(httph_bin,..) to not return faulty header strings
Unrecognized Http header names was sometimes returned as corrupt sub-binaries pointing to a stack allocated buffer. This only happened on 32-bit VM if the header name was between 16 and 20 characters long. It could in some cases lead to segmentation fault. The solution was to avoid creating sub-binary if the returned string was not part of the original binary.
Diffstat (limited to 'erts/emulator/beam/erl_bif_port.c')
-rw-r--r--erts/emulator/beam/erl_bif_port.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index 0389177fbe..2ba9dc00b7 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -1079,27 +1079,33 @@ struct packet_callback_args
Eterm res; /* Out */
int string_as_bin; /* return strings as binaries (http_bin): */
byte* aligned_ptr;
+ Uint bin_sz;
Eterm orig;
Uint bin_offs;
byte bin_bitoffs;
};
+#define in_area(ptr,start,nbytes) \
+ ((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes))
+
static Eterm
http_bld_string(struct packet_callback_args* pca, Uint **hpp, Uint *szp,
const char *str, Sint len)
{
Eterm res = THE_NON_VALUE;
Uint size;
+ int make_subbin;
if (pca->string_as_bin) {
size = heap_bin_size(len);
-
+ make_subbin = (size > ERL_SUB_BIN_SIZE
+ && in_area(str, pca->aligned_ptr, pca->bin_sz));
if (szp) {
- *szp += (size > ERL_SUB_BIN_SIZE) ? ERL_SUB_BIN_SIZE : size;
+ *szp += make_subbin ? ERL_SUB_BIN_SIZE : size;
}
if (hpp) {
res = make_binary(*hpp);
- if (size > ERL_SUB_BIN_SIZE) {
+ if (make_subbin) {
ErlSubBin* bin = (ErlSubBin*) *hpp;
bin->thing_word = HEADER_SUB_BIN;
bin->size = len;
@@ -1330,7 +1336,7 @@ BIF_RETTYPE decode_packet_3(BIF_ALIST_3)
int packet_sz; /*-------Binaries involved: ------------------*/
byte* bin_ptr; /*| orig: original binary */
byte bin_bitsz; /*| bin: BIF_ARG_2, may be sub-binary of orig */
- Uint bin_sz; /*| packet: prefix of bin */
+ /*| packet: prefix of bin */
char* body_ptr; /*| body: part of packet to return */
int body_sz; /*| rest: bin without packet */
struct packet_callback_args pca;
@@ -1391,18 +1397,18 @@ BIF_RETTYPE decode_packet_3(BIF_ALIST_3)
}
- bin_sz = binary_size(BIF_ARG_2);
+ pca.bin_sz = binary_size(BIF_ARG_2);
ERTS_GET_BINARY_BYTES(BIF_ARG_2, bin_ptr, pca.bin_bitoffs, bin_bitsz);
if (pca.bin_bitoffs != 0) {
- pca.aligned_ptr = erts_alloc(ERTS_ALC_T_TMP, bin_sz);
- erts_copy_bits(bin_ptr, pca.bin_bitoffs, 1, pca.aligned_ptr, 0, 1, bin_sz*8);
+ pca.aligned_ptr = erts_alloc(ERTS_ALC_T_TMP, pca.bin_sz);
+ erts_copy_bits(bin_ptr, pca.bin_bitoffs, 1, pca.aligned_ptr, 0, 1, pca.bin_sz*8);
}
else {
pca.aligned_ptr = bin_ptr;
}
- packet_sz = packet_get_length(type, (char*)pca.aligned_ptr, bin_sz,
+ packet_sz = packet_get_length(type, (char*)pca.aligned_ptr, pca.bin_sz,
max_plen, trunc_len, &http_state);
- if (!(packet_sz > 0 && packet_sz <= bin_sz)) {
+ if (!(packet_sz > 0 && packet_sz <= pca.bin_sz)) {
if (packet_sz < 0) {
goto error;
}
@@ -1458,7 +1464,7 @@ error:
rest = (ErlSubBin *) hp;
rest->thing_word = HEADER_SUB_BIN;
- rest->size = bin_sz - packet_sz;
+ rest->size = pca.bin_sz - packet_sz;
rest->offs = pca.bin_offs + packet_sz;
rest->orig = pca.orig;
rest->bitoffs = pca.bin_bitoffs;