[SCM] strace branch, master, updated. v4.6-128-g2fb4db3

Denys Vlasenko dvlasenk at redhat.com
Thu Sep 1 09:42:18 UTC 2011


On Thu, 2011-09-01 at 00:33 +0400, Dmitry V. Levin wrote:
> On Wed, Aug 31, 2011 at 10:32:55AM +0000, Denys Vlasenko wrote:
> > commit 2fb4db3e7aa1d6ac6b4b43f47597197492a846dd
> > Author: Denys Vlasenko <dvlasenk at redhat.com>
> > Date:   Wed Aug 31 12:26:03 2011 +0200
> > 
> >     Optimization: eliminate all remaining usages of strcat()
> >     
> >     After this change, we don't use strcat() anywhere.
> >     
> >     * defs.h: Change sprinttv() return type to char *.
> >     * time.c (sprinttv): Return pointer past last stored char.
> >     * desc.c (decode_select): Change printing logic in order to eliminate
> >     usage of strcat() - use stpcpy(), *outptr++ = ch, sprintf() instead.
> >     Also reduce usage of strlen().
> >     * stream.c (decode_poll): Likewise.
> 
> The idea behind this change is quite clear, but some hunks are questionable.
> 
> > @@ -544,41 +545,42 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
> >  			return RVAL_STR;
> >  		}
> >  
> > -		fds = (fd_set *) malloc(fdsize);
> > +		fds = malloc(fdsize);
> >  		if (fds == NULL)
> >  			fprintf(stderr, "out of memory\n");
> >  
> > -		outstr[0] = '\0';
> > +		tcp->auxstr = outstr;
> 
> I suggest to initialize tcp->auxstr as late as possible (just in case
> there is a branch of code that might fail to initialize it properly),
> better right before returning RVAL_STR.

Good idea, I just committed a change which does exactly this.


> > +		outptr = outstr;
> > +		sep = "";
> >  		for (i = 0; i < 3; i++) {
> >  			int first = 1;
> >  
> > -			tcp->auxstr = outstr;
> >  			arg = args[i+1];
> >  			if (fds == NULL || !arg ||
> >  			    umoven(tcp, arg, fdsize, (char *) fds) < 0)
> >  				continue;
> >  			for (j = 0; j < args[0]; j++) {
> >  				if (FD_ISSET(j, fds)) {
> > -					char str[11 + 3 * sizeof(int)];
> > -
> > -					if (first) {
> > -						sprintf(str, "%s%s [%u", sep,
> > -							i == 0 ? "in" :
> > -							i == 1 ? "out" :
> > -							"except", j);
> > -						first = 0;
> > -						sep = ", ";
> > +					/* +2 chars needed at the end: ']',NUL */
> > +					if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
> > +						if (first) {
> > +							outptr += sprintf(outptr, "%s%s [%u",
> > +								sep,
> > +								i == 0 ? "in" : i == 1 ? "out" : "except",
> > +								j
> > +							);
> > +							first = 0;
> > +							sep = ", ";
> > +						}
> > +						else {
> > +							outptr += sprintf(outptr, " %u", j);
> > +						}
> >  					}
> > -					else
> > -						sprintf(str, " %u", j);
> 
> I'm not sure about this change.  The new code is less readable and
> requires more room in outstr[] than the old code.
> 
> > -					cumlen += strlen(str);
> > -					if (cumlen < sizeof(outstr))
> > -						strcat(outstr, str);

Yes, it's possible that in a degenerate case old code would manage to
fit, say, a small integer into str via sprintf(str, " %u", j),
and then
cumlen += strlen(str); if (cumlen < sizeof(outstr)) strcat(outstr, str);
would successfully add it to almost full outstr.

But considering that outstr is "static char outstr[1024]", this can be
"fixed" by enlarging 1024 by about 40.


> >  		if (args[4]) {
> > -			char str[128];
> > -
> > -			sprintf(str, "%sleft ", sep);
> > -			sprinttv(tcp, args[4], bitness, str + strlen(str));
> > -			if ((cumlen += strlen(str)) < sizeof(outstr))
> > -				strcat(outstr, str);
> > +			if (outptr < end_outstr - 128) {
> > +				outptr += sprintf(outptr, "%sleft ", sep);
> > +				outptr = sprinttv(tcp, args[4], bitness, outptr);
> > +			}
> 
> The new code requires more room in outstr[] than the old code.

Enlarging outstr would fix this.
How big do you want "static char outstr[]" to be here? 1060? 1100?


> > -void
> > +char *
> >  sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf)
> >  {
> > +	int rc;
> > +
> >  	if (addr == 0)
> > -		strcpy(buf, "NULL");
> > -	else if (!verbose(tcp))
> > -		sprintf(buf, "%#lx", addr);
> > -	else {
> > -		int rc;
> > +		return stpcpy(buf, "NULL");
> >  
> > -		if (bitness == BITNESS_32
> > +	if (!verbose(tcp)) {
> > +		buf += sprintf(buf, "%#lx", addr);
> > +		return buf;
> > +	}
> 
> Why not just write it simply
> 
> 	if (!verbose(tcp))
> 		return buf + sprintf(buf, "%#lx", addr);
> 
> > +
> > +	if (bitness == BITNESS_32
> >  #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
> > -		    || personality_wordsize[current_personality] == 4
> > +	    || personality_wordsize[current_personality] == 4
> >  #endif
> > -			)
> > -		{
> > -			struct timeval32 tv;
> > -
> > -			rc = umove(tcp, addr, &tv);
> > -			if (rc >= 0)
> > -				sprintf(buf, "{%u, %u}",
> > -					tv.tv_sec, tv.tv_usec);
> > -		} else {
> > -			struct timeval tv;
> > +		)
> > +	{
> > +		struct timeval32 tv;
> > +
> > +		rc = umove(tcp, addr, &tv);
> > +		if (rc >= 0)
> > +			buf += sprintf(buf, "{%u, %u}",
> > +				tv.tv_sec, tv.tv_usec);
> 
> Why not just return buf + sprintf here,
> 
> > +	} else {
> > +		struct timeval tv;
> >  
> > -			rc = umove(tcp, addr, &tv);
> > -			if (rc >= 0)
> > -				sprintf(buf, "{%lu, %lu}",
> > -					(unsigned long) tv.tv_sec,
> > -					(unsigned long) tv.tv_usec);
> > -		}
> > -		if (rc < 0)
> > -			strcpy(buf, "{...}");
> > +		rc = umove(tcp, addr, &tv);
> > +		if (rc >= 0)
> > +			buf += sprintf(buf, "{%lu, %lu}",
> > +				(unsigned long) tv.tv_sec,
> > +				(unsigned long) tv.tv_usec);
> 
> here and
> 
> >  	}
> > +	if (rc < 0)
> > +		buf = stpcpy(buf, "{...}");
> 
> here?
> 
> > +
> > +	return buf;
> >  }

Good idea, pushed to git this version:


char *
sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf)
{
        int rc;

        if (addr == 0)
                return stpcpy(buf, "NULL");

        if (!verbose(tcp))
                return buf + sprintf(buf, "%#lx", addr);

        if (bitness == BITNESS_32
#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
            || personality_wordsize[current_personality] == 4
#endif
                )
        {
                struct timeval32 tv;

                rc = umove(tcp, addr, &tv);
                if (rc >= 0)
                        return buf + sprintf(buf, "{%u, %u}",
                                tv.tv_sec, tv.tv_usec);
        } else {
                struct timeval tv;

                rc = umove(tcp, addr, &tv);
                if (rc >= 0)
                        return buf + sprintf(buf, "{%lu, %lu}",
                                (unsigned long) tv.tv_sec,
                                (unsigned long) tv.tv_usec);
        }

        return stpcpy(buf, "{...}");
}


-- 
vda






More information about the Strace-devel mailing list