Even DJB's code is buggy. (And some others too.)
google.com
google.com
int error_intr =
#ifdef EINTR
EINTR;
#else
-1;
#endif
The (errno = error_intr) happens in this block: default:
for (;;) {
r = read(fdfile,inbuf,sizeof inbuf);
if (r == -1) {
if (errno = error_intr) continue;
_exit(23);
}
if (r == 0)
break;
if (!fetch_ascii)
substdio_put(&ss,inbuf,r);
else
for (i = 0;i < r;++i) {
if (inbuf[i] == '\n')
substdio_put(&ss,"\r",1);
substdio_put(&ss,inbuf + i,1);
}
}
break;
Like a lot of DJB code, it's hard to tell exactly what he's trying to do. He could be trying to deal with some weird platform. Where EINTR is defined to something other than 0 that code will cause the read() to be repeated whenever it returns -1 and when the code eventually gets back to the caller errno will be left set to EINTR. But on platforms where EINTR is 0, a read error will exit.Hence, here, error-handling code will be improperly invoked irrespective of whether they get a given error code or not.
Anyone want to work on a regexp for the more general condition?
http://www.google.com/codesearch?hl=en&lr=&q=if\+\(\w%2B\+%3D\+&sbtn=Search
Can anyone think of a better way to match the subset that are more likely to be bugs?
That takes out parentheses (for function calls) and structure member assignment because it might be two statements in one line (ugly and error prone as output will be exactly the same for a = b.c; if(a) {}; vs. if (a=b.c)
Helpfully, the Emacs code is commented, which helps explain the pattern:
if (errno = ack.hf_retcode) /* set errno based on returned */
return (-1); /* code, if 0, then no error */
Presumably errno is a global, and when it is set to a value other than zero, the function returns. So, it isn't an example of = being used in place of ==, at least this snippet appears to be correct.Some people have commented that it "looks kinda backwards," and I'm not sure what to make of that. My "backwards" way is perfectly correct, C-wise and math-wise, it doesn't make the code hard to understand, and it solves a real problem.
But I appreciate that it's important not to upset the other people on your team willy-nilly. So it's a bit of a quandry.
The bug searched for is using the assignment operator = instead of the equality operator ==.
But something like:
if (errno = 0) { blah(); }
is almost certainly a bug.
if (errno = error_intr) continue;
That's OK, it'll just shadow the global errno in that func, no?