summaryrefslogtreecommitdiff
path: root/source4/smb_server
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-12-20 03:12:09 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:07:32 -0500
commit545c190d2a655a3d96ea6cd19f8fecb4b63555db (patch)
treefc67bf6d632334af2a71dec12182a4ad3aef76cb /source4/smb_server
parent2057121d1433916fd2c91d4303f8ecc1eaef1215 (diff)
downloadsamba-545c190d2a655a3d96ea6cd19f8fecb4b63555db.tar.gz
samba-545c190d2a655a3d96ea6cd19f8fecb4b63555db.tar.bz2
samba-545c190d2a655a3d96ea6cd19f8fecb4b63555db.zip
r4284: fixed a problem with very large EA lists and OS/2 clients. These
checks on allocations need to go in a lot more places, but at least this is a start. (This used to be commit 99b0dac2292d72e3a77f105e8f2ef5a3838d7e1b)
Diffstat (limited to 'source4/smb_server')
-rw-r--r--source4/smb_server/trans2.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/source4/smb_server/trans2.c b/source4/smb_server/trans2.c
index 12a4be0e35..2f2629a3ea 100644
--- a/source4/smb_server/trans2.c
+++ b/source4/smb_server/trans2.c
@@ -35,36 +35,43 @@
/* grow the data allocation size of a trans2 reply - this guarantees
that requests to grow the data size later will not change the
pointer */
-static void trans2_grow_data_allocation(struct smbsrv_request *req,
+static BOOL trans2_grow_data_allocation(struct smbsrv_request *req,
struct smb_trans2 *trans,
- uint16_t new_size)
+ uint32_t new_size)
{
if (new_size <= trans->out.data.length) {
- return;
+ return True;
}
trans->out.data.data = talloc_realloc(req, trans->out.data.data, new_size);
+ return (trans->out.data.data != NULL);
}
/* grow the data size of a trans2 reply */
-static void trans2_grow_data(struct smbsrv_request *req,
+static BOOL trans2_grow_data(struct smbsrv_request *req,
struct smb_trans2 *trans,
- uint16_t new_size)
+ uint32_t new_size)
{
- trans2_grow_data_allocation(req, trans, new_size);
+ if (!trans2_grow_data_allocation(req, trans, new_size)) {
+ return False;
+ }
trans->out.data.length = new_size;
+ return True;
}
/* grow the data, zero filling any new bytes */
-static void trans2_grow_data_fill(struct smbsrv_request *req,
+static BOOL trans2_grow_data_fill(struct smbsrv_request *req,
struct smb_trans2 *trans,
- uint16_t new_size)
+ uint32_t new_size)
{
- uint16_t old_size = trans->out.data.length;
- trans2_grow_data(req, trans, new_size);
+ uint32_t old_size = trans->out.data.length;
+ if (!trans2_grow_data(req, trans, new_size)) {
+ return False;
+ }
if (new_size > old_size) {
memset(trans->out.data.data + old_size, 0, new_size - old_size);
}
+ return True;
}
@@ -1004,7 +1011,7 @@ struct find_state {
/*
fill a single entry in a trans2 find reply
*/
-static void find_fill_info(struct smbsrv_request *req,
+static BOOL find_fill_info(struct smbsrv_request *req,
struct smb_trans2 *trans,
struct find_state *state,
union smb_search_data *file)
@@ -1065,11 +1072,15 @@ static void find_fill_info(struct smbsrv_request *req,
case RAW_SEARCH_EA_LIST:
ea_size = ea_list_size(file->ea_list.eas.num_eas, file->ea_list.eas.eas);
if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
- trans2_grow_data(req, trans, ofs + 27 + ea_size);
+ if (!trans2_grow_data(req, trans, ofs + 27 + ea_size)) {
+ return False;
+ }
SIVAL(trans->out.data.data, ofs, file->ea_list.resume_key);
ofs += 4;
} else {
- trans2_grow_data(req, trans, ofs + 23 + ea_size);
+ if (!trans2_grow_data(req, trans, ofs + 23 + ea_size)) {
+ return False;
+ }
}
data = trans->out.data.data + ofs;
srv_push_dos_date2(req->smb_conn, data, 0, file->ea_list.create_time);
@@ -1200,6 +1211,8 @@ static void find_fill_info(struct smbsrv_request *req,
SIVAL(data, 0, trans->out.data.length - ofs);
break;
}
+
+ return True;
}
/* callback function for trans2 findfirst/findnext */
@@ -1211,10 +1224,8 @@ static BOOL find_callback(void *private, union smb_search_data *file)
old_length = trans->out.data.length;
- find_fill_info(state->req, trans, state, file);
-
- /* see if we have gone beyond the user specified maximum */
- if (trans->out.data.length > trans->in.max_data) {
+ if (!find_fill_info(state->req, trans, state, file) ||
+ trans->out.data.length > trans->in.max_data) {
/* restore the old length and tell the backend to stop */
trans2_grow_data(state->req, trans, old_length);
return False;