Jeremy merged across my string parinoia fixes, but forgot to enable them! :-)
authorAndrew Bartlett <abartlet@samba.org>
Tue, 18 Mar 2003 11:22:52 +0000 (11:22 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 18 Mar 2003 11:22:52 +0000 (11:22 +0000)
This patch catches up on the rest of the work - as much string checking
as is possible is done at compile time, and the rest at runtime.

Lots of code converted to pstrcpy() etc, and other code reworked to correctly
call sizeof().

Andrew Bartlett

17 files changed:
source/Makefile.in
source/client/client.c
source/client/clitar.c
source/configure.in
source/include/includes.h
source/include/safe_string.h
source/libsmb/cliconnect.c
source/libsmb/clifile.c
source/libsmb/clilist.c
source/nsswitch/winbindd_wins.c
source/smbd/negprot.c
source/smbd/reply.c
source/smbd/srvstr.c [deleted file]
source/utils/net.c
source/utils/net_rap.c
source/utils/pdbedit.c
source/utils/smbcacls.c

index a1982981028826760ae4f7e52cb43e9045782949..1084c17f08f354f9ede083b4767366fe6f4ca732 100644 (file)
@@ -322,7 +322,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
               smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
                smbd/posix_acls.o lib/sysacls.o lib/server_mutex.o \
               smbd/process.o smbd/service.o smbd/error.o \
-              printing/printfsp.o lib/util_seaccess.o smbd/srvstr.o \
+              printing/printfsp.o lib/util_seaccess.o \
                smbd/build_options.o \
               smbd/change_trust_pw.o \
               $(MANGLE_OBJ)
index 20198fc5c8da20b277148fc98fad5657edb55a7b..1248c256591429dc2d662fb0b50cb9c750fab7e9 100644 (file)
@@ -2349,7 +2349,7 @@ static struct cli_state *do_connect(const char *server, const char *share)
        char *sharename;
        
        /* make a copy so we don't modify the global string 'service' */
-       safe_strcpy(servicename, share, sizeof(servicename)-1);
+       fstrcpy(servicename, share);
        sharename = servicename;
        if (*sharename == '\\') {
                server = sharename+2;
@@ -2624,9 +2624,9 @@ static int do_message_op(void)
        make_nmb_name(&calling, global_myname(), 0x0);
        make_nmb_name(&called , desthost, name_type);
 
-       safe_strcpy(server_name, desthost, sizeof(server_name));
+       fstrcpy(server_name, desthost);
        snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
-       safe_strcat(server_name, name_type_hex, sizeof(server_name));
+       fstrcat(server_name, name_type_hex);
 
         zero_ip(&ip);
        if (have_ip) ip = dest_ip;
index 612a383ce07a3b15a247828afb2f276ed6e2e3a3..579110f75fba1229a078922c508ea76211a81cd5 100644 (file)
@@ -202,7 +202,7 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m
   /* write out a "standard" tar format header */
 
   hb.dbuf.name[NAMSIZ-1]='\0';
-  safe_strcpy(hb.dbuf.mode, amode, strlen(amode));
+  safe_strcpy(hb.dbuf.mode, amode, sizeof(hb.dbuf.mode)-1);
   oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.uid);
   oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.gid);
   oct_it((SMB_BIG_UINT) size, 13, hb.dbuf.size);
@@ -796,11 +796,11 @@ static void do_tar(file_info *finfo)
 
     DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(cur_dir)));
 
-    safe_strcpy(exclaim, cur_dir, sizeof(pstring));
+    pstrcpy(exclaim, cur_dir);
     *(exclaim+strlen(exclaim)-1)='\0';
 
-    safe_strcat(exclaim, "\\", sizeof(pstring));
-    safe_strcat(exclaim, finfo->name, sizeof(exclaim));
+    pstrcat(exclaim, "\\");
+    pstrcat(exclaim, finfo->name);
 
     DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
 
@@ -820,12 +820,12 @@ static void do_tar(file_info *finfo)
       pstring saved_curdir;
       pstring mtar_mask;
 
-      safe_strcpy(saved_curdir, cur_dir, sizeof(saved_curdir));
+      pstrcpy(saved_curdir, cur_dir);
 
       DEBUG(5, ("Sizeof(cur_dir)=%d, strlen(cur_dir)=%d, strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n", (int)sizeof(cur_dir), (int)strlen(cur_dir), (int)strlen(finfo->name), finfo->name, cur_dir));
 
-      safe_strcat(cur_dir,finfo->name, sizeof(cur_dir));
-      safe_strcat(cur_dir,"\\", sizeof(cur_dir));
+      pstrcat(cur_dir,finfo->name);
+      pstrcat(cur_dir,"\\");
 
       DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir));
 
@@ -836,16 +836,16 @@ static void do_tar(file_info *finfo)
           DEBUG(0,("                directory %s\n", cur_dir));
       }
       ntarf++;  /* Make sure we have a file on there */
-      safe_strcpy(mtar_mask,cur_dir, sizeof(pstring));
-      safe_strcat(mtar_mask,"*", sizeof(pstring));
+      pstrcpy(mtar_mask,cur_dir);
+      pstrcat(mtar_mask,"*");
       DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask));
       do_list(mtar_mask, attribute, do_tar, False, True);
-      safe_strcpy(cur_dir,saved_curdir, sizeof(pstring));
+      pstrcpy(cur_dir,saved_curdir);
     }
   else
     {
-      safe_strcpy(rname,cur_dir, sizeof(pstring));
-      safe_strcat(rname,finfo->name, sizeof(pstring));
+      pstrcpy(rname,cur_dir);
+      pstrcat(rname,finfo->name);
       do_atar(rname,finfo->name,finfo);
     }
 }
@@ -1362,8 +1362,8 @@ int cmd_setmode(void)
       return 1;
     }
 
-  safe_strcpy(fname, cur_dir, sizeof(pstring));
-  safe_strcat(fname, buf, sizeof(pstring));
+  pstrcpy(fname, cur_dir);
+  pstrcat(fname, buf);
 
   while (next_token_nr(NULL,buf,NULL,sizeof(buf))) {
     q=buf;
@@ -1459,32 +1459,32 @@ int process_tar(void)
        if (strrchr_m(cliplist[i], '\\')) {
          pstring saved_dir;
          
-         safe_strcpy(saved_dir, cur_dir, sizeof(pstring));
+         pstrcpy(saved_dir, cur_dir);
          
          if (*cliplist[i]=='\\') {
-           safe_strcpy(tarmac, cliplist[i], sizeof(pstring));
+           pstrcpy(tarmac, cliplist[i]);
          } else {
-           safe_strcpy(tarmac, cur_dir, sizeof(pstring));
-           safe_strcat(tarmac, cliplist[i], sizeof(pstring));
+           pstrcpy(tarmac, cur_dir);
+           pstrcat(tarmac, cliplist[i]);
          }
-         safe_strcpy(cur_dir, tarmac, sizeof(pstring));
+         pstrcpy(cur_dir, tarmac);
          *(strrchr_m(cur_dir, '\\')+1)='\0';
 
          DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));
          do_list(tarmac,attribute,do_tar, False, True);
-         safe_strcpy(cur_dir,saved_dir, sizeof(pstring));
+         pstrcpy(cur_dir,saved_dir);
        } else {
-         safe_strcpy(tarmac, cur_dir, sizeof(pstring));
-         safe_strcat(tarmac, cliplist[i], sizeof(pstring));
+         pstrcpy(tarmac, cur_dir);
+         pstrcat(tarmac, cliplist[i]);
          DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));
          do_list(tarmac,attribute,do_tar, False, True);
        }
       }
     } else {
       pstring mask;
-      safe_strcpy(mask,cur_dir, sizeof(pstring));
+      pstrcpy(mask,cur_dir);
       DEBUG(5, ("process_tar, do_list with mask: %s\n", mask));
-      safe_strcat(mask,"\\*", sizeof(pstring));
+      pstrcat(mask,"\\*");
       do_list(mask,attribute,do_tar,False, True);
     }
     
index 69c001f59b83c7c6cfc373157652b0ca66d12dc4..bc86473428d6f78d0e990fec458f0197431b49cc 100644 (file)
@@ -656,6 +656,24 @@ if test x"$samba_cv_immediate_structures" = x"yes"; then
    AC_DEFINE(HAVE_IMMEDIATE_STRUCTURES,1,[Whether the compiler supports immediate structures])
 fi
 
+############################################
+# check if the compiler can do immediate structures
+AC_CACHE_CHECK([if the compiler will optimize out function calls],samba_cv_optimize_out_funcation_calls, [
+    AC_TRY_LINK([
+#include <stdio.h>],
+[
+               if (0) {
+                  this_function_does_not_exist();
+               } else {
+                 return 1;
+               }
+
+],
+       samba_cv_optimize_out_funcation_calls=yes,samba_cv_optimize_out_funcation_calls=no)])
+if test x"$samba_cv_optimize_out_funcation_calls" = x"yes"; then
+   AC_DEFINE(HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS,1,[Whether the compiler will optimize out function calls])
+fi
+
 ############################################
 # check for unix domain sockets
 AC_CACHE_CHECK([for unix domain sockets],samba_cv_unixsocket, [
index 774df34de0f5295eed416180b769ff3cc91f65bb..bdd8661f6f201fe7c41a3fa3b6e9f9f2f305bd39 100644 (file)
@@ -832,6 +832,7 @@ struct printjob;
 
 /* String routines */
 
+#include "srvstr.h"
 #include "safe_string.h"
 
 #ifdef __COMPAR_FN_T
index ad7b4139a3075817e638696f1f466ecb26d9e649..61ef4bdf966aec501f40063c38c3d282188956ea 100644 (file)
@@ -129,11 +129,17 @@ size_t __unsafe_string_function_usage_here_char__(void);
     safe_strcpy(dest, src, sizeof(pstring)-PTR_DIFF(dest,pstring_base)-1)
 
 
-/* inside the _fn varients of these is a call to 'clobber_region' - which might
-   destory the stack on a buggy function.  Help the debugging process by putting
-   the function and line it was last called from into a static buffer
-
-   But only for developers */
+/* Inside the _fn variants of these is a call to clobber_region(), -
+ * which might destroy the stack on a buggy function.  We help the
+ * debugging process by putting the function and line who last caused
+ * a clobbering into a static buffer.  If the program crashes at
+ * address 0xf1f1f1f1 then this function is probably, but not
+ * necessarily, to blame. */
+
+/* overmalloc_safe_strcpy: DEPRECATED!  Used when you know the
+ * destination buffer is longer than maxlength, but you don't know how
+ * long.  This is not a good situation, because we can't do the normal
+ * sanity checks. Don't use in new code! */
 
 #ifdef DEVELOPER
 #define overmalloc_safe_strcpy(dest,src,maxlength)     safe_strcpy_fn(__FUNCTION__,__LINE__,dest,src,maxlength)
@@ -214,7 +220,4 @@ size_t __unsafe_string_function_usage_here_char__(void);
 #define strlower(s) strlower_m(s)
 #define strupper(s) strupper_m(s)
 
-#define safe_strcpy_base(dest, src, base, size) \
-    safe_strcpy(dest, src, size-PTR_DIFF(dest,base)-1)
-
 #endif
index 49b0004ac2357cf7e743925e02594dfb074370fd..54a282e805794987c0e3af2ce0c4e0b6d7614940 100644 (file)
@@ -66,7 +66,7 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
                memcpy(pword, pass, passlen);
        } else if (passlen > 0) {
                /* Plaintext mode needed, assume plaintext supplied. */
-               passlen = clistr_push(cli, pword, pass, -1, STR_TERMINATE);
+               passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
        }
 
        /* send a session setup command */
@@ -774,7 +774,7 @@ BOOL cli_send_tconX(struct cli_state *cli,
                        /*
                         * Non-encrypted passwords - convert to DOS codepage before using.
                         */
-                       passlen = clistr_push(cli, pword, pass, -1, STR_TERMINATE);
+                       passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
                } else {
                        memcpy(pword, pass, passlen);
                }
index 8e84963c09475d182d98b3d6db5ffc25b49ad40b..d86f36405ddaea9e084f67c11695877fda7065a9 100644 (file)
@@ -948,7 +948,7 @@ BOOL cli_chkpath(struct cli_state *cli, const char *path)
        pstring path2;
        char *p;
        
-       safe_strcpy(path2,path,sizeof(pstring));
+       pstrcpy(path2,path);
        trim_string(path2,NULL,"\\");
        if (!*path2) *path2 = '\\';
        
index 3884e4da828ef80b917914a916a39a74635dbe85..5bd1283ab7b47ff9697ceb0f73eaf6cd81dccbc6 100644 (file)
@@ -178,7 +178,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
                        SSVAL(param,6,info_level); 
                        SIVAL(param,8,0);
                        p = param+12;
-                       p += clistr_push(cli, param+12, mask, -1
+                       p += clistr_push(cli, param+12, mask, sizeof(param)-12
                                         STR_TERMINATE);
                } else {
                        setup = TRANSACT2_FINDNEXT;
@@ -188,7 +188,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
                        SIVAL(param,6,0); /* ff_resume_key */
                        SSVAL(param,10,8+4+2);  /* continue + resume required + close on end */
                        p = param+12;
-                       p += clistr_push(cli, param+12, mask, -1
+                       p += clistr_push(cli, param+12, mask, sizeof(param)-12
                                         STR_TERMINATE);
                }
 
index 8ddd5dc10df1522558e020cb0761c5ff47bf1f0d..a1d38ed69ad219bd724208022da82857e4499527 100644 (file)
@@ -137,8 +137,8 @@ enum winbindd_result winbindd_wins_byip(struct winbindd_cli_state *state)
                SAFE_FREE(status);
                return WINBINDD_ERROR;
            }
-           safe_strcat(response,state->request.data.winsreq,maxlen);
-           safe_strcat(response,"\t",maxlen);
+           fstrcat(response,state->request.data.winsreq);
+           fstrcat(response,"\t");
            for (i = 0; i < count; i++) {
                /* ignore group names */
                if (status[i].flags & 0x80) continue;
@@ -148,8 +148,8 @@ enum winbindd_result winbindd_wins_byip(struct winbindd_cli_state *state)
                            SAFE_FREE(status);
                            return WINBINDD_ERROR;
                        }
-                       safe_strcat(response, status[i].name, maxlen);
-                       safe_strcat(response, " ", maxlen);
+                       fstrcat(response, status[i].name);
+                       fstrcat(response, " ");
                }
            }
            /* make last character a newline */
@@ -190,16 +190,16 @@ enum winbindd_result winbindd_wins_byname(struct winbindd_cli_state *state)
                        /* Clear out the newline character */
                        response[strlen(response)-1] = ' '; 
                    }
-                   safe_strcat(response,addr,maxlen);
-                   safe_strcat(response,"\t",maxlen);
+                   fstrcat(response,addr);
+                   fstrcat(response,"\t");
                }
                size = strlen(state->request.data.winsreq) + strlen(response);
                if (size > maxlen) {
                    SAFE_FREE(ip_list);
                    return WINBINDD_ERROR;
                }   
-               safe_strcat(response,state->request.data.winsreq,maxlen);
-               safe_strcat(response,"\n",maxlen);
+               fstrcat(response,state->request.data.winsreq);
+               fstrcat(response,"\n");
                SAFE_FREE(ip_list);
        } else
                return WINBINDD_ERROR;
index c8f023514e6ce13678aada19a7fb773589f356d7..db0694a840447758bea3170fae7c365c7a07e38c 100644 (file)
@@ -167,7 +167,7 @@ static int reply_lanman2(char *inbuf, char *outbuf)
 static int negprot_spnego(char *p)
 {
        DATA_BLOB blob;
-       uint8 guid[16];
+       uint8 guid[17];
        const char *OIDs_krb5[] = {OID_KERBEROS5,
                                   OID_KERBEROS5_OLD,
                                   OID_NTLMSSP,
@@ -178,8 +178,8 @@ static int negprot_spnego(char *p)
 
        global_spnego_negotiated = True;
 
-       memset(guid, 0, 16);
-       safe_strcpy((char *)guid, global_myname(), 16);
+       ZERO_STRUCT(guid);
+       safe_strcpy((char *)guid, global_myname(), sizeof(guid)-1);
        strlower((char *)guid);
 
 #if 0
index a738baa9ffe30f12a210e7b010fc528782a7e82c..775b617df59f75a1c7c8dad97da54b2c01fb26ed 100644 (file)
@@ -161,7 +161,7 @@ int reply_tcon(connection_struct *conn,
        *service_buf = *password = *dev = 0;
 
        p = smb_buf(inbuf)+1;
-       p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1;
+       p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
        pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
        p += pwlen;
        p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
diff --git a/source/smbd/srvstr.c b/source/smbd/srvstr.c
deleted file mode 100644 (file)
index 36fecf5..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 
-   Unix SMB/CIFS implementation.
-   server specific string routines
-   Copyright (C) Andrew Tridgell 2001
-   
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-int srvstr_push(void *base_ptr, void *dest, const char *src, int dest_len, int flags)
-{
-       return push_string(base_ptr, dest, src, dest_len, flags);
-}
-
-int srvstr_pull(void *base_ptr, char *dest, const void *src, int dest_len, int src_len, 
-               int flags)
-{
-       return pull_string(base_ptr, dest, src, dest_len, src_len, flags);
-}
-
-/* pull a string from the smb_buf part of a packet. In this case the
-   string can either be null terminated or it can be terminated by the
-   end of the smbbuf area 
-*/
-int srvstr_pull_buf(void *inbuf, char *dest, const void *src, int dest_len, int flags)
-{
-       return pull_string(inbuf, dest, src, dest_len, smb_bufrem(inbuf, src), flags);
-}
index ada0ed53e130de7d46ff3ad5bcbfb489699a59cb..7588771fbc3f16aefec2950a0e14447f9bb96006 100644 (file)
@@ -241,7 +241,7 @@ BOOL net_find_dc(struct in_addr *server_ip, fstring server_name, const char *dom
                if (!lookup_dc_name(global_myname(), domain_name, server_ip, dc_name))
                        return False;
                        
-               safe_strcpy(server_name, dc_name, FSTRING_LEN);
+               fstrcpy(server_name, dc_name);
                return True;
        } else
                return False;
index 8f3dd53fa6aaa614082460f473f03d742bcb3ee2..f52eabf494e7e182e5b238bbfdede21ad19d8399 100644 (file)
@@ -638,7 +638,7 @@ static int rap_user_add(int argc, const char **argv)
        if (!(cli = net_make_ipc_connection(0)))
                 return -1;
                        
-       safe_strcpy(userinfo.user_name, argv[0], sizeof(userinfo.user_name));
+       safe_strcpy(userinfo.user_name, argv[0], sizeof(userinfo.user_name)-1);
        if (opt_flags == -1) 
                 opt_flags = 0x21; 
                        
@@ -755,7 +755,7 @@ static int rap_group_add(int argc, const char **argv)
                 return -1;
                        
        /* BB check for length 21 or smaller explicitly ? BB */
-       safe_strcpy(grinfo.group_name, argv[0], sizeof(grinfo.group_name));
+       safe_strcpy(grinfo.group_name, argv[0], sizeof(grinfo.group_name)-1);
        grinfo.reserved1 = '\0';
        grinfo.comment = smb_xstrdup(opt_comment);
        
index 9df10c21a4760d61e6efd808656d68e40f0e6560..265bda1e5d46fa2315ace59dfd41358e23a39f3e 100644 (file)
@@ -363,20 +363,21 @@ static int new_machine (struct pdb_context *in, const char *machine_in)
 {
        SAM_ACCOUNT *sam_pwent=NULL;
        fstring machinename;
+       fstring machineaccount;
        struct passwd  *pwd = NULL;
-       char name[16];
        
        fstrcpy(machinename, machine_in); 
+       machinename[15]= '\0';
 
        if (machinename[strlen (machinename) -1] == '$')
                machinename[strlen (machinename) -1] = '\0';
        
        strlower_m(machinename);
        
-       safe_strcpy (name, machinename, 16);
-       safe_strcat (name, "$", 16);
+       fstrcpy(machineaccount, machinename);
+       fstrcat(machineaccount, "$");
 
-       if ((pwd = getpwnam_alloc(name))) {
+       if ((pwd = getpwnam_alloc(machineaccount))) {
                if (!NT_STATUS_IS_OK(pdb_init_sam_pw( &sam_pwent, pwd))) {
                        fprintf(stderr, "Could not init sam from pw\n");
                        passwd_free(&pwd);
@@ -392,14 +393,14 @@ static int new_machine (struct pdb_context *in, const char *machine_in)
 
        pdb_set_plaintext_passwd (sam_pwent, machinename);
 
-       pdb_set_username (sam_pwent, name, PDB_CHANGED);
+       pdb_set_username (sam_pwent, machineaccount, PDB_CHANGED);
        
        pdb_set_acct_ctrl (sam_pwent, ACB_WSTRUST, PDB_CHANGED);
        
        pdb_set_group_sid_from_rid(sam_pwent, DOMAIN_GROUP_RID_COMPUTERS, PDB_CHANGED);
        
        if (NT_STATUS_IS_OK(in->pdb_add_sam_account (in, sam_pwent))) {
-               print_user_info (in, name, True, False);
+               print_user_info (in, machineaccount, True, False);
        } else {
                fprintf (stderr, "Unable to add machine! (does it already exist?)\n");
                pdb_free_sam (&sam_pwent);
@@ -435,12 +436,13 @@ static int delete_user_entry (struct pdb_context *in, const char *username)
 
 static int delete_machine_entry (struct pdb_context *in, const char *machinename)
 {
-       char name[16];
+       fstring name;
        SAM_ACCOUNT *samaccount = NULL;
        
-       safe_strcpy (name, machinename, 16);
-       if (name[strlen(name)] != '$')
-               safe_strcat (name, "$", 16);
+       fstrcpy(name, machinename);
+       name[15] = '\0';
+       if (name[strlen(name)-1] != '$')
+               fstrcat (name, "$");
 
        if (!NT_STATUS_IS_OK(pdb_init_sam (&samaccount))) {
                return -1;
index a5cee0dae1202593a9069cf138ffd0e3747bb578..bce64df960416822aef3028b3170d885dbfec0c8 100644 (file)
@@ -916,7 +916,7 @@ You can string acls together with spaces, commas or newlines\n\
        if (filename[0] != '\\') {
                pstring s;
                s[0] = '\\';
-               safe_strcpy(&s[1], filename, sizeof(pstring)-1);
+               safe_strcpy(&s[1], filename, sizeof(pstring)-2);
                pstrcpy(filename, s);
        }