Help us understand the problem. What is going on with this article?

Let's encryptのバグはRustで実装していたら防げたの?

はじめに

Let's encryptのバグの原因はポインタに起因する実装ミスでした。
「Rustはいいぞ」と言うためだけにRustで実装した場合を検証してみます。

原因はなんだった?

詳しくは
https://jovi0608.hatenablog.com/entry/2020/03/09/094737
のステキなまとめを見たほうがいいのですが、

シンプルにすると、このような実装です。

fail.go
func main() {
    var out []*int
    for i := 0; i < 3; i++ {
        out = append(out, &i)
    }
    fmt.Println("Values:", *out[0], *out[1], *out[2])
    fmt.Println("Addresses:", out[0], out[1], out[2])
}

ValuesもAddressesも[0]~[2]で同じ値が表示されます。
ループカウンタを値渡しではなく、
参照渡しをして保管してしまったことが要因です。

同じような実装ミスをC++で書くとこんな感じです。

fail.cpp
#include <iostream>
#include <vector>

int main(){

    std::vector<int*> out;

    for(int i = 0; i < 3; i++){
        out.push_back(&i);
    }

    std::cout << out[0] << std::endl;
    std::cout << out[1] << std::endl;
    std::cout << out[2] << std::endl;

    std::cout << *out[0] << std::endl;
    std::cout << *out[1] << std::endl;
    std::cout << *out[2] << std::endl;

    return 0;
}

これも同じような結果になります。

Rustで書いてみると

good.rust
fn main() {

    let mut out:Vec<&i32> = vec![];

    for i in 0..3{
        out.push(&i);
    }

    println!("{:?}", out);
}

コンパイル時に、このようなエラーが出ます。

6 |         out.push(&i);
  |         ---      ^^ borrowed value does not live long enough
  |         |
  |         borrow later used here

Rustは生存期間を厳密に検証してくれるので、とても安全です!

実際のLet's encryptの実装ミスは、ループの中で関数呼び出しを挟んでいるので
気づくのが難しいとも感じました。

こんなケースではRustは本当に頼もしいです。

Rustはいいぞ

コンパイラにめっちゃ怒られるぞ。
コンパイラに怒られるのに快感を感じるようになったら立派なRust使いです。

komasayuki
自動車業界のエンジニア、未踏スーパークリエーター、最近AWS Solution Architect Professionalを取ったばかり。双子のパパ。猫が好き。猫が好き。猫が好き。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした