From owner-freebsd-hackers@FreeBSD.ORG Sat Apr 24 11:27:33 2004 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3F18216A4CE for ; Sat, 24 Apr 2004 11:27:33 -0700 (PDT) Received: from mail.1plan.net (ns1.1plan.net [216.240.143.74]) by mx1.FreeBSD.org (Postfix) with SMTP id 0D50A43D58 for ; Sat, 24 Apr 2004 11:27:31 -0700 (PDT) (envelope-from aanton@reversedhell.net) Received: (qmail 37353 invoked by uid 98); 24 Apr 2004 18:33:31 -0000 Received: from aanton@reversedhell.net by cp by uid 101 with qmail-scanner-1.20 (clamscan: 0.65. Clear:RC:1(81.196.32.25):SA:0(-99.5/5.0):. Processed in 1.955386 secs); 24 Apr 2004 18:33:31 -0000 X-Spam-Status: No, hits=-99.5 required=5.0 X-Qmail-Scanner-Mail-From: aanton@reversedhell.net via cp X-Qmail-Scanner: 1.20 (Clear:RC:1(81.196.32.25):SA:0(-99.5/5.0):. Processed in 1.955386 secs) Received: from unknown (HELO reversedhell.net) (81.196.32.25) by ns1.1plan.net with SMTP; 24 Apr 2004 18:33:29 -0000 Message-ID: <408AB18B.9020906@reversedhell.net> Date: Sat, 24 Apr 2004 21:27:23 +0300 From: Anton Alin-Adrian User-Agent: Mozilla Thunderbird 0.5 (X11/20040303) X-Accept-Language: en-us, en MIME-Version: 1.0 To: freebsd-hackers@freebsd.org X-Enigmail-Version: 0.83.3.0 X-Enigmail-Supports: pgp-inline, pgp-mime Content-Type: multipart/mixed; boundary="------------060702070401020708010807" Subject: FreeBSD's malloc problem ? X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Apr 2004 18:27:33 -0000 This is a multi-part message in MIME format. --------------060702070401020708010807 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Hello hackers ! Before anything else, I must mention I am running FreeBSD 4.9-RELEASE, and that is the OS where I encounter the problem. I was developing some functions fooling around for parsing some bigger opensource project's config file and look what happened: There are many functions inside, only adjust_spaces(char *s) is the interesting one! The problem does *not* exist on Linux systems. Now, before getting into anything fancy, I want to mention that I am horribly ill and this posting may be terribly lame and the only one who has faults may be me with my code. BUT, if that is not the case, then this might be a bug in FreeBSD malloc's mechanism. Ok here it goes. The problem is at line 68 in the attached file, in function adjust_spaces(char *s): ---code snippet--- char *adjust_spaces(char *s) { char *tmp; int i=0,j=0,count=0; int is_leading=0,last_space=0; tmp = (char *) malloc(strlen(s)); // line 68 ........ ........ } ---code snippet--- If the function is called exactly as in the code, with the buffer setup to: ---code snippet--- int main (void) { char buf[]="allowed_ip abcde#"; // like that, other combination // have the same result char *s; if (is_definition(buf)) fprintf(stderr,"DEFINITION found\n"); else fprintf(stderr,"Nothing found\n"); split_line(buf); } ---code snippet--- then at line 90 and possibly 79 too: tmp[j]=s[i]; // line 90 the first character of the string pointed to by *tmp (which was malloced before, at line 68) will *overwrite* the null terminating '\0' character of the string pointed to by *s (and given as input to the function). This later results in an infinite counter loop and an integer overflow, but the integer overflow will not become reality because the program will try to read/write from invalid memory locations and will crash receiving a segmentation fault. ALL THIS never happens, if at line 68 I use this code: tmp = (char *) malloc(strlen(s)+1); // new line 68 adds +1 In the attached file t.c, you will find the corrected version of line 68, just like above. I do not understand the malloc mechanism (sadly, i will appreciate any links for reading as much as a gift), and this is why I do not see (I may be just way too dizzy) the logic of why adding +1 fixes the problem. Please note that adding +1 is not necessary on Linux, I just tested it, but on FreeBSD without adding +1, in rare situations like the one I presented it will crash exactly like I described. Linux works fine on all situations, including this one which crashes on FreeBSD (the very same code). If I am just talking crap please forgive me. I really want to understand what's going on, is it me who is doing it the wrong way? The code is just fooling around to get things working properly, it is not beautified and optimized (yet). PS: another possibility is that I have a 1 byte overflow inside the string pointed to by *s, even before calling the adjust_spaces(char *s) function; but I simply cannot focus anymore,so please help me a bit. Thanks for your time. Sincerely Yours, -- Alin-Adrian Anton Reversed Hell Networks GPG keyID 0x1E2FFF2E (2963 0C11 1AF1 96F6 0030 6EE9 D323 639D 1E2F FF2E) gpg --keyserver pgp.mit.edu --recv-keys 1E2FFF2E --------------060702070401020708010807 Content-Type: text/plain; name="t.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="t.c" #include #include char *remove_comments(char *s) { char *tmp; int i=0; tmp=(char*) malloc (strlen(s)); while ((s[i]!='\0') && (s[i]!='#')) { tmp[i]=s[i]; i++; } tmp[i]='\0'; return tmp; } char *remove_unallowed(char *s) { char *tmp; int i=0,j=0; tmp=(char*) malloc(strlen(s)); while (s[i]!='\0') { if ( (isalnum(s[i])) || (isspace(s[i])) || (s[i]==',') || (s[i]=='_') || (s[i]=='.') ) { tmp[j]=s[i]; j++; } i++; } tmp[j]='\0'; return tmp; } char *remove_unallowed_section(char *s) { char *tmp; int i=0,j=0; tmp=(char*) malloc(strlen(s)); while (s[i]!='\0') { if ( (isalnum(s[i])) || (s[i]=='_') ) { tmp[j]=s[i]; j++; } i++; } tmp[j]='\0'; return tmp; } char *adjust_spaces(char *s) { char *tmp; int i=0,j=0,count=0; int is_leading=0,last_space=0; tmp = (char *) malloc(strlen(s)+1); //fprintf(stderr,"Converting |%s| length=%d\n",s,strlen(s)); while (s[i]!='\0') { //fprintf(stderr,"i=%d j=%d len=%d s[len]=%d\n",i,j,strlen(s),s[strlen(s)]); //fprintf(stderr,"tmp= |%s|\n",tmp); //sleep(1); if (isspace(s[i])) { //fprintf(stderr,"s1=|%s|\n",s); if (is_leading==0) is_leading=1; if ((!count) && (is_leading!=1)) { tmp[j]=s[i]; j++; } if (is_leading==1) is_leading=-1; count++; } else { //fprintf(stderr,"s2=|%s|\n",s); is_leading=-1; count=0; tmp[j]=s[i]; j++; } i++; } // end while if (isspace(tmp[j-1])) --j; tmp[j]='\0'; return tmp; } int is_section(char *s) { int i; int br_left=0,br_right=0; char *tmp; s=remove_comments(s); for (i=0;i0) && (i