diff -ur samba-2.0.10/source/include/smb.h samba-2.0.10-security/source/include/smb.h
--- samba-2.0.10/source/include/smb.h	2001-06-23 12:52:20.000000000 +0400
+++ samba-2.0.10-security/source/include/smb.h	2005-05-21 21:51:17.206995728 +0400
@@ -256,6 +256,7 @@
 #define ERRlock 33 /* Lock request conflicts with existing lock */
 #define ERRunsup 50 /* Request unsupported, returned by Win 95, RJS 20Jun98 */
 #define ERRfilexists 80 /* File in operation already exists */
+#define ERRinvalidparam 87
 #define ERRcannotopen 110 /* Cannot open the file specified */
 #define ERRunknownlevel 124
 #define ERRrename 183
@@ -1893,4 +1894,7 @@
 
 #define SAFE_NETBIOS_CHARS ". -_"
 
+#ifndef SAFE_FREE
+#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0)
+#endif
 #endif /* _SMB_H */
diff -ur samba-2.0.10/source/include/version.h samba-2.0.10-security/source/include/version.h
--- samba-2.0.10/source/include/version.h	2001-06-23 17:23:59.000000000 +0400
+++ samba-2.0.10-security/source/include/version.h	2005-05-21 21:51:17.227992536 +0400
@@ -1 +1 @@
-#define VERSION "2.0.10"
+#define VERSION "2.0.10-security-rollup"
diff -ur samba-2.0.10/source/smbd/filename.c samba-2.0.10-security/source/smbd/filename.c
--- samba-2.0.10/source/smbd/filename.c	2000-03-17 01:59:44.000000000 +0300
+++ samba-2.0.10-security/source/smbd/filename.c	2005-05-21 21:51:17.403965784 +0400
@@ -172,7 +172,7 @@
    * StrnCpy always null terminates.
    */
 
-  StrnCpy(orig_name, full_orig_name, namelen);
+  StrnCpy(orig_name, full_orig_name, MIN(namelen, sizeof(orig_name)-1));
   if(!case_sensitive)
     strupper( orig_name );
 
diff -ur samba-2.0.10/source/smbd/ipc.c samba-2.0.10-security/source/smbd/ipc.c
--- samba-2.0.10/source/smbd/ipc.c	2000-03-30 02:20:06.000000000 +0400
+++ samba-2.0.10-security/source/smbd/ipc.c	2005-05-21 21:51:17.269986152 +0400
@@ -3550,18 +3550,18 @@
 	uint16 *setup=NULL;
 	int outsize = 0;
 	uint16 vuid = SVAL(inbuf,smb_uid);
-	int tpscnt = SVAL(inbuf,smb_vwv0);
-	int tdscnt = SVAL(inbuf,smb_vwv1);
-	int mprcnt = SVAL(inbuf,smb_vwv2);
-	int mdrcnt = SVAL(inbuf,smb_vwv3);
-	int msrcnt = CVAL(inbuf,smb_vwv4);
+	unsigned int tpscnt = SVAL(inbuf,smb_vwv0);
+	unsigned int tdscnt = SVAL(inbuf,smb_vwv1);
+	unsigned int mprcnt = SVAL(inbuf,smb_vwv2);
+	unsigned int mdrcnt = SVAL(inbuf,smb_vwv3);
+	unsigned int msrcnt = CVAL(inbuf,smb_vwv4);
 	BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
 	BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
-	int pscnt = SVAL(inbuf,smb_vwv9);
-	int psoff = SVAL(inbuf,smb_vwv10);
-	int dscnt = SVAL(inbuf,smb_vwv11);
-	int dsoff = SVAL(inbuf,smb_vwv12);
-	int suwcnt = CVAL(inbuf,smb_vwv13);
+	unsigned int pscnt = SVAL(inbuf,smb_vwv9);
+	unsigned int psoff = SVAL(inbuf,smb_vwv10);
+	unsigned int dscnt = SVAL(inbuf,smb_vwv11);
+	unsigned int dsoff = SVAL(inbuf,smb_vwv12);
+	unsigned int suwcnt = CVAL(inbuf,smb_vwv13);
 
 	memset(name, '\0',sizeof(name));
 	fstrcpy(name,smb_buf(inbuf));
@@ -3572,31 +3572,48 @@
   
 	if (tdscnt)  {
 		if((data = (char *)malloc(tdscnt)) == NULL) {
-			DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
+			DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt));
 			return(ERROR(ERRDOS,ERRnomem));
 		} 
+		if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
+			goto bad_param;
+		if (smb_base(inbuf)+dsoff+dscnt > inbuf + size)
+			goto bad_param;
+
 		memcpy(data,smb_base(inbuf)+dsoff,dscnt);
 	}
 
 	if (tpscnt) {
 		if((params = (char *)malloc(tpscnt)) == NULL) {
-			DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
+			DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt));
+			SAFE_FREE(data);
 			return(ERROR(ERRDOS,ERRnomem));
 		} 
+		if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
+			goto bad_param;
+		if (smb_base(inbuf)+psoff+pscnt > inbuf + size)
+			goto bad_param;
+
 		memcpy(params,smb_base(inbuf)+psoff,pscnt);
 	}
 
 	if (suwcnt) {
 		int i;
 		if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
-          DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16))));
-		  return(ERROR(ERRDOS,ERRnomem));
-        } 
+			DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16))));
+			SAFE_FREE(data);
+			SAFE_FREE(params);
+			return(ERROR(ERRDOS,ERRnomem));
+		} 
+		if (inbuf+smb_vwv14+(suwcnt*SIZEOFWORD) > inbuf + size)
+			goto bad_param;
+		if ((smb_vwv14+(suwcnt*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(suwcnt*SIZEOFWORD) < (suwcnt*SIZEOFWORD)))
+			goto bad_param;
+
 		for (i=0;i<suwcnt;i++)
 			setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
 	}
 
-
 	if (pscnt < tpscnt || dscnt < tdscnt) {
 		/* We need to send an interim response then receive the rest
 		   of the parameter/data bytes */
@@ -3608,7 +3625,7 @@
 	/* receive the rest of the trans packet */
 	while (pscnt < tpscnt || dscnt < tdscnt) {
 		BOOL ret;
-		int pcnt,poff,dcnt,doff,pdisp,ddisp;
+		unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
       
 		ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
 
@@ -3619,19 +3636,19 @@
 				DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
 					 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
 			}
-			if (params)
-				free(params);
-			if (data)
-				free(data);
-			if (setup)
-				free(setup);
+			SAFE_FREE(params);
+			SAFE_FREE(data);
+			SAFE_FREE(setup);
 			return(ERROR(ERRSRV,ERRerror));
 		}
 
 		show_msg(inbuf);
       
-		tpscnt = SVAL(inbuf,smb_vwv0);
-		tdscnt = SVAL(inbuf,smb_vwv1);
+		/* Revise total_params and total_data in case they have changed downwards */
+		if (SVAL(inbuf,smb_vwv0) < tpscnt)
+			tpscnt = SVAL(inbuf,smb_vwv0);
+		if (SVAL(inbuf,smb_vwv1) < tdscnt)
+			tdscnt = SVAL(inbuf,smb_vwv1);
 
 		pcnt = SVAL(inbuf,smb_vwv2);
 		poff = SVAL(inbuf,smb_vwv3);
@@ -3644,17 +3661,36 @@
 		pscnt += pcnt;
 		dscnt += dcnt;
 		
-		if (dscnt > tdscnt || pscnt > tpscnt) {
-			exit_server("invalid trans parameters\n");
-		}
+		if (dscnt > tdscnt || pscnt > tpscnt)
+			goto bad_param;
 		
-		if (pcnt)
+		if (pcnt) {
+			if (pdisp+pcnt >= tpscnt)
+				goto bad_param;
+			if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
+				goto bad_param;
+			if (smb_base(inbuf) + poff + pcnt >= inbuf + bufsize)
+				goto bad_param;
+			if (params + pdisp < params)
+				goto bad_param;
+
 			memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
-		if (dcnt)
+		}
+
+		if (dcnt) {
+			if (ddisp+dcnt >= tdscnt)
+				goto bad_param;
+			if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
+				goto bad_param;
+			if (smb_base(inbuf) + doff + dcnt >= inbuf + bufsize)
+				goto bad_param;
+			if (data + ddisp < data)
+				goto bad_param;
+
 			memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);      
+		}
 	}
-	
-	
+
 	DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
 		 name,tdscnt,tpscnt,suwcnt));
 	
@@ -3694,4 +3730,12 @@
 		return(ERROR(ERRSRV,ERRnosupport));
 	
 	return(outsize);
+
+  bad_param:
+
+	DEBUG(0,("reply_trans: invalid trans parameters\n"));
+	SAFE_FREE(data);
+	SAFE_FREE(params);
+	SAFE_FREE(setup);
+	return(ERROR(ERRSRV,ERRerror));
 }
diff -ur samba-2.0.10/source/smbd/nttrans.c samba-2.0.10-security/source/smbd/nttrans.c
--- samba-2.0.10/source/smbd/nttrans.c	2000-04-24 21:27:30.000000000 +0400
+++ samba-2.0.10-security/source/smbd/nttrans.c	2005-05-21 21:51:17.314979312 +0400
@@ -2575,11 +2575,14 @@
     params = (char *)malloc(total_parameter_count);
   if (total_data_count > 0)
     data = (char *)malloc(total_data_count);
- 
+
   if ((total_parameter_count && !params)  || (total_data_count && !data) ||
       (setup_count && !setup)) {
+    SAFE_FREE(setup);
+    SAFE_FREE(params);
+    SAFE_FREE(data);
     DEBUG(0,("reply_nttrans : Out of memory\n"));
-    return(ERROR(ERRDOS,ERRnomem));
+    return ERROR(ERRDOS,ERRnomem);
   }
 
   /* Copy the param and data bytes sent with this request into
@@ -2588,64 +2591,112 @@
   num_data_sofar = data_count;
 
   if (parameter_count > total_parameter_count || data_count > total_data_count)
-    exit_server("reply_nttrans: invalid sizes in packet.\n");
+    goto bad_param;
 
   if(setup) {
-    memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
     DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count));
-    dump_data(10, setup, setup_count);
+    if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) ||
+	(smb_nt_SetupStart + setup_count < setup_count))
+      goto bad_param;
+    if (smb_nt_SetupStart + setup_count > length)
+      goto bad_param;
+    
+    memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
   }
   if(params) {
-    memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
     DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count));
-    dump_data(10, params, parameter_count);
+    if ((parameter_offset + parameter_count < parameter_offset) ||
+	(parameter_offset + parameter_count < parameter_count))
+      goto bad_param;
+    if (smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)
+      goto bad_param;
+    
+    memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
   }
   if(data) {
-    memcpy( data, smb_base(inbuf) + data_offset, data_count);
     DEBUG(10,("reply_nttrans: data_count = %d\n",data_count));
-    dump_data(10, data, data_count);
+    if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count))
+      goto bad_param;
+    if (smb_base(inbuf) + data_offset + data_count > inbuf + length)
+      goto bad_param;
+    
+    memcpy( data, smb_base(inbuf) + data_offset, data_count);
+
   }
 
   if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
     /* We need to send an interim response then receive the rest
        of the parameter/data bytes */
     outsize = set_message(outbuf,0,0,True);
-    send_smb(Client,outbuf);
+    if (!send_smb(Client,outbuf))
+      exit_server("reply_nttrans: send_smb failed.");
 
     while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
       BOOL ret;
-
+      uint32 parameter_displacement;
+      uint32 data_displacement;
+      
       ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
-
+      
       if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
-        outsize = set_message(outbuf,0,0,True);
-        if(ret) {
-		DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
-        } else {
-		DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
-			 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
+	outsize = set_message(outbuf,0,0,True);
+	if(ret) {
+	  DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
+	} else {
+	  DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
+		   (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
 	}
-        if(params)
-          free(params);
-        if(data)
-          free(data);
-        if(setup)
-          free(setup);
-        return(ERROR(ERRSRV,ERRerror));
+	goto bad_param;
       }
       
       /* Revise total_params and total_data in case they have changed downwards */
-      total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
-      total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
-      num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount));
-      num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount));
-      if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count)
-        exit_server("reply_nttrans2: data overflow in secondary nttrans packet\n");
-
-      memcpy( &params[ IVAL(inbuf, smb_nts_ParameterDisplacement)], 
-              smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count);
-      memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)],
-              smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count);
+      if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count)
+	total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
+      if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count)
+	total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
+      
+      parameter_count = IVAL(inbuf,smb_nts_ParameterCount);
+      parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset);
+      parameter_displacement = IVAL(inbuf, smb_nts_ParameterDisplacement);
+      num_params_sofar += parameter_count;
+      
+      data_count = IVAL(inbuf, smb_nts_DataCount);
+      data_displacement = IVAL(inbuf, smb_nts_DataDisplacement);
+      data_offset = IVAL(inbuf, smb_nts_DataOffset);
+      num_data_sofar += data_count;
+
+      if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) {
+	DEBUG(0,("reply_nttrans2: data overflow in secondary nttrans packet"));
+	goto bad_param;
+      }
+
+      if (parameter_count) {
+	if (parameter_displacement + parameter_count >= total_parameter_count)
+	  goto bad_param;
+	if ((parameter_displacement + parameter_count < parameter_displacement) ||
+	    (parameter_displacement + parameter_count < parameter_count))
+	  goto bad_param;
+	if (smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize)
+	  goto bad_param;
+	if (params + parameter_displacement < params)
+	  goto bad_param;
+	
+	memcpy( &params[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count);
+      }
+      
+      if (data_count) {
+	if (data_displacement + data_count >= total_data_count)
+	  goto bad_param;
+	if ((data_displacement + data_count < data_displacement) ||
+	    (data_displacement + data_count < data_count))
+	  goto bad_param;
+	if (smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize)
+	  goto bad_param;
+	if (data + data_displacement < data)
+	  goto bad_param;
+	
+	memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count);
+      }
     }
   }
 
@@ -2714,4 +2765,10 @@
   return outsize; /* If a correct response was needed the call_nt_transact_xxxx 
 		     calls have already sent it. If outsize != -1 then it is
 		     returning an error packet. */
+ bad_param:
+
+  SAFE_FREE(params);
+  SAFE_FREE(data);
+  SAFE_FREE(setup);
+  return ERROR(ERRDOS,ERRinvalidparam);
 }
diff -ur samba-2.0.10/source/smbd/password.c samba-2.0.10-security/source/smbd/password.c
--- samba-2.0.10/source/smbd/password.c	2000-03-17 01:59:48.000000000 +0300
+++ samba-2.0.10-security/source/smbd/password.c	2005-05-21 21:51:17.336975968 +0400
@@ -770,7 +770,7 @@
       if (!ok && lp_username(snum)) {
 	char *auser;
 	pstring user_list;
-	StrnCpy(user_list,lp_username(snum),sizeof(pstring));
+	StrnCpy(user_list,lp_username(snum),sizeof(pstring)-1);
 
 	pstring_sub(user_list,"%S",lp_servicename(snum));
 	  
diff -ur samba-2.0.10/source/smbd/reply.c samba-2.0.10-security/source/smbd/reply.c
--- samba-2.0.10/source/smbd/reply.c	2001-06-23 12:51:24.000000000 +0400
+++ samba-2.0.10-security/source/smbd/reply.c	2005-05-21 21:51:17.378969584 +0400
@@ -1413,6 +1413,9 @@
 
         for (i=numentries;(i<maxentries) && !finished;i++)
         {
+	  /* check to make sure we have room in the buffer */
+	  if ( ((PTR_DIFF(p, outbuf))+DIR_STRUCT_SIZE) > BUFFER_SIZE )
+	  	break;
           finished = 
             !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
           if (!finished)
@@ -3122,6 +3125,9 @@
     
 
 		for (i=first;i<first+num_to_get;i++) {
+			/* check to make sure we have room in the buffer */
+			if ( (PTR_DIFF(p, outbuf)+28) > BUFFER_SIZE )
+				break;
 			put_dos_date2(p,0,queue[i].time);
 			CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
 			SSVAL(p,5,printjob_encode(SNUM(conn), 
diff -ur samba-2.0.10/source/smbd/trans2.c samba-2.0.10-security/source/smbd/trans2.c
--- samba-2.0.10/source/smbd/trans2.c	2000-04-24 21:27:31.000000000 +0400
+++ samba-2.0.10-security/source/smbd/trans2.c	2005-05-21 21:51:17.402965936 +0400
@@ -201,7 +201,6 @@
   int16 open_ofun = SVAL(params,12);
   int32 open_size = IVAL(params,14);
   char *pname = &params[28];
-  int16 namelen = strlen(pname)+1;
 
   pstring fname;
   mode_t unixmode;
@@ -213,7 +212,7 @@
   BOOL bad_path = False;
   files_struct *fsp;
 
-  StrnCpy(fname,pname,namelen);
+  pstrcpy(fname,pname);
 
   DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
 	   fname,open_mode, open_attr, open_ofun, open_size));
@@ -2185,7 +2184,7 @@
 	unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
 	unsigned int tran_call = SVAL(inbuf, smb_setup0);
 	char *params = NULL, *data = NULL;
-	int num_params, num_params_sofar, num_data, num_data_sofar;
+	unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
 
 	if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
 		/* Queue this open message as we are the process of an
@@ -2203,8 +2202,9 @@
 	/* All trans2 messages we handle have smb_sucnt == 1 - ensure this
 	   is so as a sanity check */
 	if (suwcnt != 1) {
-		DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
-		return(ERROR(ERRSRV,ERRerror));
+		DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
+		DEBUG(2,("Transaction is %d\n",tran_call));
+		ERROR(ERRDOS,ERRinvalidparam);
 	}
     
 	/* Allocate the space for the maximum needed parameters and data */
@@ -2215,11 +2215,9 @@
   
 	if ((total_params && !params)  || (total_data && !data)) {
 		DEBUG(2,("Out of memory in reply_trans2\n"));
-        if(params)
-          free(params);
-        if(data)
-          free(data); 
-		return(ERROR(ERRDOS,ERRnomem));
+		SAFE_FREE(params);
+		SAFE_FREE(data); 
+		return ERROR(ERRDOS,ERRnomem);
 	}
 
 	/* Copy the param and data bytes sent with this request into
@@ -2230,20 +2228,37 @@
 	if (num_params > total_params || num_data > total_data)
 		exit_server("invalid params in reply_trans2");
 
-	if(params)
-		memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
-	if(data)
-		memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
+	if(params) {
+		unsigned int psoff = SVAL(inbuf, smb_psoff);
+		if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
+			goto bad_param;
+		if (smb_base(inbuf) + psoff + num_params > inbuf + length)
+			goto bad_param;
+		memcpy( params, smb_base(inbuf) + psoff, num_params);
+	}
+	if(data) {
+		unsigned int dsoff = SVAL(inbuf, smb_dsoff);
+		if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
+			goto bad_param;
+		if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
+			goto bad_param;
+		memcpy( data, smb_base(inbuf) + dsoff, num_data);
+	}
 
 	if(num_data_sofar < total_data || num_params_sofar < total_params)  {
 		/* We need to send an interim response then receive the rest
 		   of the parameter/data bytes */
 		outsize = set_message(outbuf,0,0,True);
-		send_smb(Client,outbuf);
+		if (!send_smb(Client,outbuf))
+			exit_server("reply_trans2: send_smb failed.");
 
 		while (num_data_sofar < total_data || 
 		       num_params_sofar < total_params) {
 			BOOL ret;
+			unsigned int param_disp;
+			unsigned int param_off;
+			unsigned int data_disp;
+			unsigned int data_off;
 
 			ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
 			
@@ -2255,26 +2270,55 @@
 				else
 					DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
 						 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
-				if(params)
-					free(params);
-				if(data)
-					free(data);
-				return(ERROR(ERRSRV,ERRerror));
+				goto bad_param;
 			}
       
 			/* Revise total_params and total_data in case
                            they have changed downwards */
-			total_params = SVAL(inbuf, smb_tpscnt);
-			total_data = SVAL(inbuf, smb_tdscnt);
-			num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
-			num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
+			if (SVAL(inbuf, smb_tpscnt) < total_params)
+				total_params = SVAL(inbuf, smb_tpscnt);
+			if (SVAL(inbuf, smb_tdscnt) < total_data)
+				total_data = SVAL(inbuf, smb_tdscnt);
+
+			num_params = SVAL(inbuf,smb_spscnt);
+			param_off = SVAL(inbuf, smb_spsoff);
+			param_disp = SVAL(inbuf, smb_spsdisp);
+			num_params_sofar += num_params;
+
+			num_data = SVAL(inbuf, smb_sdscnt);
+			data_off = SVAL(inbuf, smb_sdsoff);
+			data_disp = SVAL(inbuf, smb_sdsdisp);
+			num_data_sofar += num_data;
+
 			if (num_params_sofar > total_params || num_data_sofar > total_data)
-				exit_server("data overflow in trans2");
+				goto bad_param;
 			
-			memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
-				smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
-			memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
-				smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
+			if (num_params) {
+				if (param_disp + num_params >= total_params)
+					goto bad_param;
+				if ((param_disp + num_params < param_disp) ||
+						(param_disp + num_params < num_params))
+					goto bad_param;
+				if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
+					goto bad_param;
+				if (params + param_disp < params)
+					goto bad_param;
+
+				memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
+			}
+			if (num_data) {
+				if (data_disp + num_data >= total_data)
+					goto bad_param;
+				if ((data_disp + num_data < data_disp) ||
+						(data_disp + num_data < num_data))
+					goto bad_param;
+				if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
+					goto bad_param;
+				if (data + data_disp < data)
+					goto bad_param;
+
+				memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
+			}
 		}
 	}
 	
@@ -2367,4 +2411,10 @@
 	return outsize; /* If a correct response was needed the
 			   call_trans2xxx calls have already sent
 			   it. If outsize != -1 then it is returning */
+
+  bad_param:
+
+	SAFE_FREE(params);
+	SAFE_FREE(data);
+	return (ERROR(ERRDOS,ERRinvalidparam));
 }