On Wednesday 16 April 2014 20:01:38 Cathey, Jim wrote:
> Generally C compilers assume that an address
> passed to a function (free(p)) _might_ be dereferenced,
> and so would not optimize away the memset(p,...)
>
> If a particular C compiler thinks it knows what
> free() is, and that it doesn't dereference its argument,
> then it might think it was justified in doing this.
>
> That's a broken C compiler if you ask me, unless
> you _can_ tell it not to make assumptions about what
> particularly-named functions do. (Else cross-compiling,
> or developing in/for peculiar environments is impossible.)
>
> A C compiler that _knows_ free() doesn't dereference its
> argument _is_ entirely justified in eliminating the
> memset. The tool to tell the C compiler that there
> are other factors operating behind the C compiler's
> back is "volatile", which basically tells it "you don't
> know everything here, so stop screwing around and do exactly
> what I say." It's an overlarge hammer in this case, though.
>
> -- Jim
Hi,
just out of curiosity and for me to learn, would code
like this avoid optimization?
void getPassword(void)
{
char pwd[64];
if (GetPassword(pwd, sizeof(pwd))) {
/* checking of password, secure operations, etc */
}
memset(pwd, 0, sizeof(pwd));
if (pwd[0] != '\0') {
printf("memory not zeroed");
exit(1)
}
}
or would the compiler see that we read just first char
and zero only that and force us to check every
char of pwd?
Ciao,
Tito
> -----Original Message-----
> From: [email protected] [mailto:[email protected]] On
> Behalf Of Denys Vlasenko
> Sent: Wednesday, April 16, 2014 10:52 AM
> To: Tito
> Cc: busybox
> Subject: Re: [PATCH] memset 0 in obscure is optimized away by compiler
>
> On Wed, Apr 16, 2014 at 6:47 PM, Tito <[email protected]> wrote:
> > Hi,
> > while reading some interesting stuff about memset being optimized
> > away by compilers if the variable is not read after the memset call
> > I recalled there was something similar in libbb/obscure.c file:
> >
> > static int string_checker(const char *p1, const char *p2)
> > {
> > int size, i;
> > /* check string */
> > int ret = string_checker_helper(p1, p2);
> > /* make our own copy */
> > char *p = xstrdup(p1);
> >
> > /* reverse string */
> > i = size = strlen(p1);
> > while (--i >= 0) {
> > *p++ = p1[i];
> > }
> > p -= size; /* restore pointer */
> >
> > /* check reversed string */
> > ret |= string_checker_helper(p, p2);
> >
> > /* clean up */
> > memset(p, 0, size);
> >
> > free(p);
> >
> > return ret;
> > }
>
> $ make libbb/obscure.s
>
> and I see the memset (inlined by compiler):
>
> cld
> xorl %eax, %eax # tmp76
> movl %ebx, %edi # p.101,
> movl %esi, %ecx # D.7349, D.7349
> rep
> stosb
>
> Perhaps because compiler doesn't know that free(p) doesn't use
> the contents of *p.
>
> >
> > - /* clean up */
> > - memset(p, 0, size);
> > + /* clean up, don't use memset as it is optimized away by compiler */
> > + /*memset(p, 0, size);*/
> > + nuke_str(p);
> > free(p);
>
> This may be unnecessary wrt correctness (memset isn't eliminated),
> but it is also _fewer bytes of code_!
>
> Applied to git, thanks!
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox