冗長な記述とエラーとの相関とか
Using redundancies to find errors
邪悪なpdfはこちら→
http://www.stanford.edu/~engler/tse-redundant.pdf
Abstract.
Programmers generally attempt to perform useful work. If they performed an action, it was because they believed
it served some purpose. Redundant operations violate this belief. However, in the past redundant operations
have been typically regarded as minor cosmetic problems rather than serious errors. This paper demonstrates
that in fact many redundancies are as serious as traditional hard errors (such as race conditions or null
pointer dereferences). We experimentally test this idea by writing and applying five redundancy checkers to a
number of large open source projects, finding many errors. We then show that even when redundancies are
harmless they strongly correlate with the presence of traditional hard errors. Finally we show how flagging
redundant operations gives a way to detect mistakes and omissions in specifications. For example, a locking
specification that binds shared variables to their protecting locks can use redundancies to detect missing
bindings by flagging critical sections that include no shared state.
んで、例としてあげられていたのはたとえばこういうもの
/* linux2.4.1/net/atm/lec.c:lec addr delete: */
for(entry=priv->lec arp tables[i];
entry != NULL;
entry=next) } /* BUG: never reached */
next = entry->next;
if (...) {
lec_arp_remove(priv->lec_arp_tables, entry);
kfree(entry);
}
lec_arp_unlock(priv);
return 0;
}
/* linux2.4.5-ac8/fs/ntfs/unistr.c:ntfs collate names */
for (cnt = 0; cnt < min(name1_len, name2_len); ++cnt) {
c1 = le16_to_cpu(*name1++);
c2 = le16_to_cpu(*name2++);
if (ic) {
if (c1 < upcase len)
c1 = le16_to_cpu(upcase[c1]);
if (c2 < upcase len)
c2 = le16_to_cpu(upcase[c2]);
}
/* [META] stray terminator! */
if (c1 < 64 && legal_ansi_char_array[c1] & 8);
return err val;
if (c1 < c2)
return -1;
/* linux2.4.1/net/ipv6/raw.c:rawv6 getsockopt */
switch (optname) {
case IPV6 CHECKSUM:
if (opt->checksum == 0)
val = -1;
else
val = opt->offset;
/* BUG: always falls through */
default:
return -ENOPROTOOPT;
}
len=min(sizeof(int),len);
/* linux2.4.5-ac8/drivers/net/wan/sbni.c:sbni ioctl */
slave = dev get by name(tmpstr);
if(!(slave && slave->flags & IFF UP &&
dev->flags & IFF UP))
{
.../* print some error message, back out */
return ..EINVAL;
}
if (slave) { ... }
/* BUG: !slave is impossible */
else {
... /* print some error message */
return ..ENOENT;
}
/* linux2.4.5-ac8/drivers/scsi/qla1280.c:
qla1280 putq t */
srb_p = q->q_first;
while (srb_p)
srb_p = srb p->s_next;
if (srb_p) { /* BUG: this branch is never taken*/
sp->s prev = srb_p->s_prev;
if (srb_p->s_prev)
srb_p->s prev->s_next = sp;
else
q->q_first = sp;
srb_p->s_prev = sp;
sp->s next = srb_p;
} else {
sp->s_prev = q->q_last;
q->q_last->s_next = sp;
q->q_last = sp;
}
X. CONCLUSION
This paper explored the hypothesis that redundancies,
like type errors, flag higher-level correctness mistakes. We
evaluated the approach using five checkers which we applied to
the Linux, OpenBSD, and PostgreSQL. These simple analyses
found many surprising (to us) error types. Further, they correlated
well with known hard errors: redundancies seemed to flag
confused or poor programmers who were prone to other errors.
These indicators could be used to identify low-quality code
in otherwise high-quality systems and help managers choose
audit candidates in large code bases.