Slide 1

Slide 1 text

STORES 株式会社 Ebisu.mobile #8 大忘年会 2024年 12月 20日 ・ Naoto Uwaseki 10年もののバグを退治した話

Slide 2

Slide 2 text

● 上関直人/うわせき なおと ● STORES 決済/Androidエンジニア ● アイコンはモルモット ● 趣味 ○ エレキギター ᷚ🎸 自己紹介 2

Slide 3

Slide 3 text

STORES 決済 の紹介 3

Slide 4

Slide 4 text

STORES 決済 の技術の紹介 4 決済アプリ 決済端末 レシート プリンター サーバー ● Bluetooth接続 ● コマンド生成をC言語でライブラリ化

Slide 5

Slide 5 text

10年もののバグ退治......その経緯 5 ● 最初に問題を検知したのは2020年 ○ Android10の端末でクラッシュが発生している ○ ネイティブクラッシュということだけが分かった ● Android側のバグだろうか?と思って様子を見ていた...... ネイティブクラッシュ C言語などのネイティブコードでのクラッシュこと。

Slide 6

Slide 6 text

10年もののバグ退治......その経緯 6 ところが、、、

Slide 7

Slide 7 text

10年もののバグ退治......その経緯 7 ● 一向に解消しない 😨 ● 断続的に調査を行うものの有益な情報は得られず ● なにかしら発生条件があるらしい ○ クラッシュ率自体は高くなかった

Slide 8

Slide 8 text

10年もののバグ退治......その経緯 8 2024年 真剣に向き合おうと決意 🔥

Slide 9

Slide 9 text

10年もののバグ退治......クラッシュレポートから分かること 9 ● ネイティブクラッシュをFirebase Crashlyticsに送る

Slide 10

Slide 10 text

10年もののバグ退治......クラッシュレポートから分かること 10 ● ネイティブクラッシュをFirebase Crashlyticsに送る

Slide 11

Slide 11 text

10年もののバグ退治......クラッシュレポートから分かること 11 ● ネイティブクラッシュをFirebase Crashlyticsに送る

Slide 12

Slide 12 text

10年もののバグ退治......クラッシュレポートから分かること 12 ● ネイティブクラッシュをFirebase Crashlyticsに送る

Slide 13

Slide 13 text

10年もののバグ退治......傾向・条件をつかむ! 13 ● スタックトレースからは何も情報が得られなかった ● FirebaseにはユーザーIDを送っている 💡 ○ 他のログと突き合わせることで情報が増える ○ クラッシュの傾向・条件がつかめないだろうか......?

Slide 14

Slide 14 text

10年もののバグ退治......傾向・条件をつかむ! 14 ● クラッシュしたユーザーはプリンターを利用している! ○ プリンターのモデルはバラバラ ● 印刷処理に何かしら問題がある......?

Slide 15

Slide 15 text

STORES 決済 の技術の紹介 15 決済アプリ 決済端末 レシート プリンター サーバー ● Bluetooth接続 ● コマンド生成をC言語でライブラリ化

Slide 16

Slide 16 text

10年もののバグ退治......泥臭いデバッグ 16 ● プリンターへ送るコマンドの生成処理を C言語 で実装、 ライブラリ化して利用している ○ とても怪しい ● 二分探索的にコードをコメントアウト -> 実行......という 泥臭い作業のすえクラッシュを引き起こす関数を特定 💪

Slide 17

Slide 17 text

10年もののバグ退治......原因特定! 17 ● 社内ライブラリの印刷データの作成処理にバグがあった ● 具体的にはmemset関数の使い方が誤っていた ○ バッファーオーバーフローが発生 😱 バッファーオーバーフロー プログラムがバッファに割り当てられた空間よりも大きなデータを書き込むことで、 データがバッファ境界からあふれ、バッファの範囲外のメモリを上書きし、元々その メモリにあったデータを破壊してしまうことを指す。 (Wikipedia・バッファオーバーフロー)

Slide 18

Slide 18 text

10年もののバグ退治......原因特定! 18 ● 非常に単純化すると、以下のような実装があった memset(アドレス, 1バイトの値, 3) ● アドレスが指す領域に、1バイトの値を、3バイト分書く ● なぜか「3」がハードコーディングさていた 🤔🤔🤔

Slide 19

Slide 19 text

10年もののバグ退治......原因特定! 19 ● なぜか「3」がハードコーディングさていた 🤔🤔🤔 memset(アドレス, 1バイトの値, 3) ● 1バイトの値を1バイト書き込むことを前提に領域確保 ● 2バイト余分に書き込むのでバッファーオーバーフロー

Slide 20

Slide 20 text

10年もののバグ退治......対応をリリース 20 ● 想定外の領域の値が書き換わってしまったことが原因 ○ 書き換わった領域が参照されるとクラッシュ ■ 発生率の低さ & 謎のスタックトレースの要因 ● ライブラリ実装当初からこうなっていた ○ 10年以上前! ● 1行修正してリリースすると......

Slide 21

Slide 21 text

10年もののバグ退治......対応をリリース 21

Slide 22

Slide 22 text

10年もののバグ退治......対応をリリース 22 倒せた 🎉

Slide 23

Slide 23 text

10年もののバグ退治からの教訓 23 ● スタックトレースが理解不能でも慌てない 👌 ● 特殊なクラッシュでもツールを駆使して情報を増やす 💡 ● 他の情報と組み合わせることで発生条件を絞り込める 💡 ● 諦めない気持ち ✊

Slide 24

Slide 24 text

10年もののバグを退治した話 24 完