株式会社クリアコード > ククログ

ククログ


バグを踏んだら開発元(upstream)に報告するのをまわりに勧めてみよう

はじめに

クリアコードでは、普段の開発で実践していることを開発スタイルとしていくつかまとめています。 そのなかの一つが、「問題を見つけたらupstreamで直す」です。

今回は、自分達で実践するだけではなくて、「問題を見つけたらupstreamで直す」のをまわりに勧めてうまくいった事例(Kermitの不具合を報告)を紹介します。

Kermitとは

Kermitとはシリアル通信でファイル転送をするためのプロトコルであり、組み込み用途にEmbedded Kermitが用意されています。 今回の事例では、シリアル通信でファイルを転送するのにEmbedded KermitのJavaの実装を採用していました。

どんなバグを踏んだのか

Kermitを利用してファイル転送をしていると、ファイルの内容が破損するという問題に遭遇しました。 Embedded KermitのJavaの実装は10年以上修正されていないので、それなりに実装が枯れていると思われるのにも関わらず、です。

問題はKermitのJavaの実装におけるパケットのシーケンス番号の取扱いにありました。

Kermitのプロトコルは仕様がPDFで公開されています。

このPDFの4章に記載されているパケットフォーマットの仕様を見るとわかるのですが、4.1.のパケットのフィールドにおけるシーケンス番号の説明には次のようにあります。*1

The packet sequence number, modulo 64, ranging from 0 to 63.  Sequence numbers "wrap around" to 0 after each group of 64 packet

パケットのシーケンス番号のとりうる値は0から63であり、63の次は0に戻るmodulo 64で処理しなければならないと規定されています。

この問題に対して、次のようなパッチを対策として当てることになりました。

diff --git a/src/com/lucent/kermit/Kermit.java b/src/com/lucent/kermit/Kermit.java
index cef2545..ece21d2 100644
--- a/src/com/lucent/kermit/Kermit.java
+++ b/src/com/lucent/kermit/Kermit.java
@@ -1294,7 +1294,7 @@ public class Kermit {
   /** Returns the time we should wait for a timeout a*/
   public int getTimeout() { return sendTime; }
 
-  protected int getNextSeq( int num ) { return (num >=64)?0:num+1; }
+  protected int getNextSeq( int num ) { return (num >=63)?0:num+1; }
 
   public String toString() {
   return "kermit:"

修正前の処理だとgetNextSeq()の引数であるnumが63の場合に、次のシーケンス番号としてインクリメントした値(64)を返してしまいます。 ここで次のシーケンス番号は仕様書の規定どおりに0を返さなければいけないので、仕様に合致していません。 従ってシーケンス番号の判定条件が明らかに誤っています。

修正後の判定条件ではnumが63以上の場合には次のシーケンス番号として仕様通りに0を返すようになっています。

上記のJavaの実装では1パケット(シーケンス)で最大1024バイトまで送れるようになっていました。*2 そのため、この問題が発覚するのは、サイズが64KBを越えるファイルを転送した場合に限られていました。

10年ものの不具合を踏みぬいたということは、もしかすると64KBを越えるファイルサイズのシリアル通信という用途にJavaの実装は使われていなかったのかもしれません。

問題は無事解決、その後は?

これでシリアル通信で、転送したファイルが壊れてしまう問題が解決しました。 解決はしたのですが、開発元へのフィードバックはまだなされていないようでした。

そこで、開発元にこのパッチをフィードバックしてみませんか、と開発に参加していたプロジェクト内で働きかけてみました。 独自にパッチをメンテナンスし続けるにはそれなりのコストがかかります。むしろ開発元に反映してその成果物を利用するほうが、結果としてメンテナンスコストが下がるというメリットが得られるためです。

そのプロジェクトではフリーソフトウェアに対する理解がもともとあったので、働きかけが実を結び作成されたパッチは無事開発元に反映されました。

まとめ

今回は、バグを踏んだら開発元に報告するのをまわりに勧めてうまくいった事例を紹介しました。

遭遇した問題に対するパッチも作成して報告するというのは理想ではありますが、パッチを作成することそれ自体は必須ではありません。 バグ報告した内容が再現可能であれば、それだけでも開発元にとって助けになります。

フリーソフトウェアのバグを踏み抜いて、まだそのフィードバックをしていない事例を見つけたら、ぜひまわりにもバグ報告することを勧めてみてください。 フリーソフトウェアをよりよくすることで、その普及に繋げることができます。

*1 p15を参照のこと

*2 7.1 Long Packetsという仕様を実装しているコードにおける最大値。

2016-10-27

«前の記事: v0.14 Outputプラグインの仕様解説 最新記事 次の記事: Ruby 2.4の新機能:rb\_gc\_adjust\_memory_usage() - バインディングとGCの関係を改善するAPI»
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|