http://www.tedunangst.com/flak/post/different-fixes-for-same-bug で変数の扱いについて書いている。
- int ret; - ret = ssl3_handshake_mac(s, NID_md5, sender, len, p); - p += ret; - ret += ssl3_handshake_mac(s, NID_sha1, sender, len, p); - return (ret);
これがバグなのは返り値を確認していないからなのだけれども、 LibreSSL では修正ついでに変数名も変えて、
+ int ret_md5, ret_sha1; + + ret_md5 = ssl3_handshake_mac(s, NID_md5, sender, len, p); + if (ret_md5 == 0) + return 0; + p += ret_md5; + ret_sha1 = ssl3_handshake_mac(s, NID_sha1, sender, len, p); + if (ret_sha1 == 0) + return 0; + return (ret_md5 + ret_sha1);
こうしたという話。
OpenSSL では元の ret を残して、
int ret, sha1len; ret=ssl3_handshake_mac(s,NID_md5,sender,len,p); if(ret == 0) return 0; p+=ret; sha1len=ssl3_handshake_mac(s,NID_sha1,sender,len,p); if(sha1len == 0) return 0; ret+=sha1len; return(ret);
というコードに修正している。
最初は「どっちも同じじゃん」と思ったのだけど、tedu によれば、この違いは大きいらしい。
たしかによく見ると、LibreSSL では ret_* が「関数からの返り値であり、チェックすべきもの」という意味で命名されているのに対し、OpenSSL では「return するためのもの」という意味に見える。
こうした違いが潜在的に goto fail などのバグの原因になるのだとか。