Google の Rust スタイルガイド

2026/10/22 4:11

Google の Rust スタイルガイド

RSS: https://news.ycombinator.com/rss

要約▶

Japanese Translation:

本書は、Google における Rust プログラミング言語の使用を支援する包括的なスタイルガイドであり、基本的なフォーマットを超えて、API デザイン、所有権、並行処理、およびプラットフォーム固有の実装要件(Android、ChromeOS、Fuchsia、Chromium を含む)に関するガイダンスを含んでいます。主な目標は、広大なソフトウェアエコシステム内でのコードの可読性、保守性、そして大規模な変更への対応を最優先することにあります。これらのルールは、通常、公式の公開 Rust スタイルガイドから派生しており、組織的な目標や独自のコードベース要件と衝突しない限りそのように採用されています。より広い Rust エコシステムに沿いつつ、多様なプラットフォームに適応することで、google3、Chrome、Android のようなプロジェクト全体で一貫性を確保しています。これらの慣約を遵守することは、Google ソフトウェアスタック全体の品質を大幅に向上させ、新規開発者のオンボーディングを容易にし、大規模なアップデートの円滑化を実現します。結局のところ、本書は安全性、エラーハンドリング、テストフレームワーク、並行処理モデルに関する技術的制約など、既存のエコシステムとの整合性を保ちつつ、すべての新コードが従うべき現在のルール集として機能します。

本文

Google Rust スタイルガイド

背景と目標

スコープ

  • 対象コードベース:Android、Chromium および関連するプロジェクト。
    • このガイドは他とのコードベースとの協議に基づいて開発され、適用の意向がある。
    • コードベースごとの独自の厳密さに関する規則が存在する可能性がある。

目標

C++ スタイルガイドと同様に、以下の目標から派生したスタイル規則を採用する:

  • 可読性と保守性を優先:記述性よりもコードの長期的な維持可能性を重視する。
  • 自動化と一貫性を支援:大規模な変更(LSCs)の実施を容易にする。
  • Rust エコシステムとの整合:既存の Rust 慣習に依存し、学習コストを削減する。
  • 実利のある規則のみ:各開発者が常に心に留める具体的な利益をもたらす規則を採用する。
  • 議論の回避:合理的な意見の相違が生じやすく、再論争が起きるスタイル問題を防ぐ。

ガイドの適用方針

  • 公的な Rust スタイルガイドに従う:本ガイドと抵触しない限り、公式な Rust の慣習(例:
    rustfmt
    で強制される形式)を優先する。
    • 「抵触」とは、本ガイドが推奨しないパターンを採用したり、Rust 公式ガイドラインに反する事例を含むことを指す。
  • 大規模変更(LSCs)への対応:意図的な再構成フレンドリーなパターンを採用し、ツールとの親和性を高める。

API デザインとコードの組織化

コードの種類による適用方針

コードタイプ方針留意点
ライブラリコード必須:API デザインに関する規則を厳格に適用する。汎用的な再利用性を重視し、抽象化を避けないようにする。
アプリケーションコード推奨:強力な推奨事項として扱う。特定の課題解決のためには単純さと直観性を優先する。過剰な一般化を避ける。

Crate とモジュールの構成

  • Crate(クレート):コンパイル単位であり、常にルートモジュールを含む。
  • Rust モジュール:Crate 内のコード組織単位。名称の可視性を制御し、ファイルやディレクトリ構造と連動する。

クレートサイズの推奨事項

  • 小さなクレートを好む:理想は単一のファイル(一つの抽象化に焦点)である。コードを可能な限り小さなクレートに分割する。
    • Chromium では高粒度のライブラリターゲットが推奨される理由:ビルドグラフの依存関係管理、並列コンパイルの効率化。
  • 大きなクレートの例外:トレイト実装の整合性が必須な場合や、大規模な基盤ライブラリ構築時のみ許容される。

ファイルレイアウトのルール

  • フラットな構造を推奨:
    rust_library
    (一つの Crate)は単一のディレクトリに置かれる。
    • サブディレクトリでファイル整理を行わないこと。クレートが大きくなりすぎた兆候とみなされ、分割すべきである。
  • 例外(//third_party):Cargo も併せてビルドされる場合のみ、標準の Cargo ディレクトリ構造を使用する。

名前付け規則

  • リーフモジュール:プライマリユーザー定義項目の名前に基づいて命名する(例:
    mod foo
    ,
    foo.rs
    )。
    • 特定の抽象化ではない場合は任意の名前でも可。
  • ノンリーフモジュール:API を実装せず、宣言と再エクスポートのみを含むべき。
    • 例外:少量の「ものをまとめる」実装コードは OK。
    • 許可されるサブモジュール:
      mod test
      ,
      #[cxx::bridge]
      など。

インポートと使用法

グローブインポート(Globs)の使用制限

以下の状況を除き、グローブインポートを使用しないこと。

  • use super::*
    (インラインモジュール用)
  • use enum::*
    (Enum メソッド本体など)
  • pub use submodule::*
    (ノンリーフモジュール用)
  • C++ 互換性のため:名前空間統合に使用する際のみ(例:
    absl::Status
    のようなアクセス)。

根拠

  • グローブインポートはコード精査者の負担を増加させる。
    • xrefs が存在しないため、型がどこから来るか把握しにくくなる。

Use ステートメントの形式

  • imports_granularity = Module
    を設定として採用する。
  • 悪い例:ルートとネストを混ぜる
    use foo::{Foo, bar::Bar, baz::Baz};
  • 良い例:階層を保つ
    use foo::{Foo, bar::{Bar, Baz}};

ローカルスコープでのトレイトインポート

  • ファイル全体で使われない限り、関数内部でのみトレイトをインポートする。
    fn foo(x: u8) {
        use std::str::FromStr; // 関数内でのみ
        let string: String = x.parse();
    }
    

トップレベル関数の呼出方

  • 他のモジュール/クレートからのトップレベル関数は、モジュール名付きで呼び出す。
    use std::mem;
    let x = mem::transmute(y); // 推奨
    
  • 例外:
    • C++ のフリー関数など十分に区別された名前を持つ場合。
    • 小さい単一目的のファーストパーティクレートからの場合。
    • モジュール名衝突が避けられない場合。

タイプ名の参照方法

  • 原則:デフォルトでモジュールパスを使用せず、トップレベル型名(例:
    Regex
    )を参照する(
    use regex::Regex
    でインポート)。
  • 例外:
    • 曖昧さ回避が必要な場合(例:
      io::Error
      )。
    • リネームが必要な場合(例:
      use std::io::Error as IoError
      )。
    • 多数の HIR タイプを含む
      hir
      モジュールなど。
    • マクロや生成コード、多くの依存関係がある場合。

インポートメカニズム

  • Chromium では
    chromium::import!()
    を使用する。

コードフォーマットと美しさ

フォーマット設定

  • 行幅:100 列 (
    max_width = 100
    )
  • ヘックスリテラル:小文字 (
    hex_literal_case = Lower
    )
  • マクロマッチャーを整形する (
    format_macro_matchers = true
    )
  • 不可視文字のエスケープを使用(
    \u{200D}
    など)。

自動フォーマットの除外(
#[rustfmt::skip]
)

以下の状況のみ許容される:

  • 手動整列:可読性を保つために行を整列させる場合、行列構築関数など。
  • 生成されたコード:
    genrule
    を使用して管理する場合。
  • 禁止:個人好みに基づく除外は行わないこと。

所有権と借用

スマートポインタの回避

  • Rc と Arc を避ける:ユニークな所有権と借用を優先する。
    • 例外:代替構造が複雑化しすぎてしまう場合のみ使用(レビュー時に議論が必要)。

コピー戦略

  • 深層コピーよりも借用を優先:
    .clone()
    は借用関係の複雑化による実用的選択を除き、避けるべき。
  • Rc/Arc のクローンは例外:参照カウントポインタのクローンにはこのアドバイスは適用しない。

関数の引数と戻り値の設計

柔軟な参照タイプを使用

データ自体への参照を優先し、スマートポインターやラッパーへの参照を避ける。

使用する代わりに理由
&T
&Box<T>
ボックス内のデータを借用するのではなく、直接借用する方が効率的。
&[T]
&Vec<T>
任意のスライスを受け付ける方が汎用性が高い。
&str
&String
文字列スライスを受け付ける方が汎用性が高い。
Option<&T>
&Option<T>
Option 内のデータを直接借用する。

イテレータの優先

  • 戻り値:
    Vec<T>
    よりも、イテレータ(または
    impl Iterator
    )を返すことを優先する。
    • 例外:呼出側が所有ベクトルを必要とする場合、実装が自然にベクトルを構築する場合、ランダムインデックスが必要な場合など。
  • 引数:スライス
    &[T]
    よりも、イテレータまたは
    impl IntoIterator
    を受け付けることを優先する。
    • 理由:コピー不要、柔軟性、チェーンとの親和性。

Into の使用

  • ライブラリ API で
    T
    ではなく
    impl Into<T>
    を考慮する場合もあるが、コード肥大化とのバランスに注意する。
  • 例外:アプリケーションコードは原則として
    impl Into<T>
    を使用しないこと。

エラー報告の選定

メカニズム使用場面例
Option原因が明確で、さらなる詳細は不要な失敗。欠落やパース不整合など。
fn checked_add(...) -> Option<u32>
Result<T, E>回復可能な失敗で、呼出側がエラーハンドリングが必要(I/O など)。
fn open_file(...) -> Result<File, io::Error>
panic!バグや不変違反(回避不可能なエラー)。コードの欠陥を示す。インデックス越え時など。
  • Enum を bool より優先:パラメータの目的が明確でない場合は、bool ではなく Enum を使用する。
  • API コントラクト:
    Option
    、
    Result
    、
    panic!
    のいずれかを選択し一貫させる。

タイプとトレイト

新タイプ(Newtype)の活用

以下の場合は型エイリアスの代わりに newtype を使用する:

  • 顕著な意味的違いがある場合。
  • 独自の API を持つ必要がある場合。
  • 将来の基礎タイプ変更の柔軟性を望む場合。
  • 安全性のため混同を避ける必要がある場合(例:
    Date
    と
    Day
    )。

命名フィールドの優先

  • タプルインデックス(
    .0
    )よりも命名フィールドを持つ構造体を使用する。
    • 例外:Newtype タプル構造や、文脈内で混乱がない場合。

トリート実装と定義

実装の順序

  • 低レベルライブラリ:ユーザーのニーズを予期し、トレイト実装を提供する。
  • アプリケーションコード:必要に応じてトレイト実装を追加する。

メソッド対トレイト

  • 標準ライブラリの目的に一致するメソッドがある場合は、そのトレイトを実装する(例:
    FromStr
    )。
  • 手動実装より
    #[derive()]
    を優先する。

ジェネリクス対 dyn トリート

  • ライブラリコード:ジェネリクス(
    T: Trait
    )を
    dyn Trait
    より好む。
    • 理由:効率性(vtable の不要化)、一部トレイトは Dyn 互換ではないため。

トリート定義の制限

以下の目的以外にトレイトを定義しない:

  • 汎用プログラミング(
    T: Trait
    )のため。
  • impl Trait
    /
    dyn Trait
    を扱うため。
  • 拡張トレイトを定義するため。
    • それ以外は固有の実装を使用する。

拡張トレイト(Extension Traits)

  • 目的:異なるクレートのタイプにメソッドを追加するためだけのものであり、一般化や動的ディスパッチは意図しない。
  • 命名:接尾辞
    ~Ext
    を付ける(例:
    ForeignTypeExt
    )。
  • 所有権:元のタイプを持つチームが拡張トレイトも保持すべき。

標準トレイトの実装方針

トリートポリシー注意点
Copy常に実装(可能なら)。管理を単純化する。非 Copy フィールドを持つ場合は不可。
Clone外部リソースを含まない限り、ほぼ全ての実装。-
Default
new()
またはデフォルト状態を持つ場合。
-
PartialEq / Eqユーザーが
==
を使う場合は
PartialEq
(詳細な比較)から始める。
反射性が必要な場合
Eq
も実装。
PartialOrd / Ord
<
/
>
を使う場合は
PartialOrd
から始める。
完全順序化が必要なら
Ord
。
Hash / Eqマップキーまたはキャッシュ対象の場合。-
From重要な構築方法を持つ場合、
::new_from_foo()
も追加推奨。
-

オプション構造体と Default

  • 全ての公開フィールドを持つ構造体が「オプション袋」として使われる場合、
    Default
    を実装する。
    • 理由:構文
      Struct { ..Default::default() }
      の利用が可能になる。

From 実装とコンストラクタ

  • 主要な構築方法の一つとして期待される重要な
    From
    実装を持つ場合、専用メソッド(
    ::new()
    など)も追加する。

公開 API の安全性

  • Enum:他のチームが使う場合は
    #[non_exhaustive]
    を適用する。(オントロジー定義や 2 状態のみなど例外あり)
  • Struct:全ての公開フィールドを持つ場合は
    #[non_exhaustive]
    を適用する。(FRU 構文使用など例外あり)

並行性とマクロ

Chromium 特有の制限

  • async / .await を使用しない。
  • シーケンス(std::sync):新しいスレッドを開始する代わりに使用する。
  • Mutex:Fuchsia 向けには
    fuchsia_sync::Mutex
    を使用。

マクロとコード生成

以下の優先順位で API を設計する:

  1. 通常の関数、型、トレイト、モジュール(マクロ回避)。
  2. macro_rules!
    マクロ。
  3. 他のコード生成戦略。
  4. proc_macro
    。
  • 理由:IDE 機能の低下、開発者の学習コスト増、大規模変更の困難さ。

命名規則

メソッドと関数

  • Rust 標準ライブラリおよび Naming Guide を従う。
  • 接頭辞:変換系は
    as_...
    、
    to_...
    、
    into_...
    を使用。
  • 初期化関数:コンストラクタは
    new()
    、結果型は
    try_new()
    。値対値変換は
    from_foo()
    。

ライフタイム

  • 記述的な名前を付ける(特にタイプライフタイム)。
  • 例外:
    Cow
    のような一般的な抽象化、匿名(
    '_
    )、単一文字のローカル境界。

ジェネリクス

  • 単一または多文字の短い名前を使用し、対象する種類に関連付ける。
  • T
    、
    U
    は比較的非縛り文脈で可。

クロージャーを受け付けるアクセッサ

.with_foo()
アクセッサは以下の状況で推奨:

  • プロパティが Mutex/RefCell などでラップされており、スコープを制御する場合。
  • プロパティの変更後に検証が必要な場合(クローンが高価な場合など)。

Getter / Setter の命名

目的関数名説明
取得
foo()
&T
を返す。
可変取得
foo_mut()
&mut T
を返す。
取り出し
take_foo()
値を取り除き、古い値を返す(None など)。
設定
set_foo()
新しい値を設定する。
置換
replace_foo()
新しい値を設定し、古い値を返す。

コンテキスト文字列とアサーション

  • アサーションの理由や文脈を明示する(
    assert!(cond, "message")
    )。
    • 誤用フラグ、バグ報告、ログ出力などに役立つ。
  • 禁止:単に条件を繰り返すだけのメッセージ(例:"values should always be sorted")は避ける。

条件付きとイテレータチェーン

  • 直接反復が明らかな場合:イテレータコンビネータチェーンは避ける。
    • for
      ループヘッダーにチェーンを組まない(変数に割り当てる)。
    • 複雑なチェーンは可読性を損なうため、明示的な
      for
      ループが推奨される。
  • 例外:チェーン自体がロジックを提供する場合や、簡潔に表現できる場合。

パニックとコード実行

  • catch_unwind を使用しない:Chrome/Android/Fuchsia は
    panic=abort
    環境のため。
    • 例外:深層防御の試み(レビュー推奨)。
  • main() 前の実行禁止:静的初期化順序など、
    main()
    より前にコードを実行させない(
    ctor
    クレート使用禁止)。

unsafe コードと不安定機能

  • unsafe
    コードは同等の safe な実装がない限り書かない。
    • 安全性コメントと技術的正当性を記述する。
  • 不安定機能を原則として使わない(特定プロジェクトでのみ例外)。

ドキュメント化

コメントの役割

公開 API のドキュメントに

///
または
//!
を使用する。実装コメントには
//
を使用し、両方を混合してよい。

記載すべき項目

  • 例:関数の動作イメージを与える十分な例を含む(全てではないが、クレートの挙動を把握できる)。
  • パニックケース:入力が不適切な場合の動作を明示する。
  • unsafe / 不変:安全上の注意事項や制約を明記する。
  • キャピタライゼーション・句読点:正確に使用する。

記載すべきでない項目

  • プログラミング言語の基礎知識の説明(例:「FileSystem はモックです」)。
    • コードがすでに表している事項への単なる繰り返しは避ける。

ドキュメントコメントの書式

  • ///:関数、構造体、Enum などの項目向け。
  • //!:モジュールまたはライブラリ自体向け(ファイル上部)。
  • Markdown 構文の使用を推奨する。
  • ///
    よりマクロ生成ドキュメントの方が読みやすい。

テストとビルド

テストフレームワーク

プラットフォームフレームワーク特徴
Chrome
rust_gtest_interop
C++ テストバイナリとの統合。
Fuchsia
#[fuchsia::test]
Fuchsia CI 連携。

タイプ推論と明示

  • 型推論を過剰に使用しない。変数宣言に明示的な型を優先し、Turbofish を避けられる場合は避ける。
    • 推奨追加:汎用戻り値(
      .into()
      ,
      .parse()
      )、複雑なイテレータチェーンなど。

パターンマッチングの活用

  • unwrap
    よりパターンマッチングを優先し、パニック回避をコンパイラーに証明する。
    // 推奨:コンパイラ検証
    if let Some(value) = option {
        use_value(value);
    }
    

Expect の使用

  • パニックが必要な場合は、理由を記載した
    expect
    を使用する(
    unwrap
    より)。

マッチ式の完全性

  • #[non_exhaustive]
    Enum に対しては、ワイルドカードアームを含めるか
    if let
    /
    match ... else {}
    を使用し、欠落したバリアントを明示する。

その他の実装上の注意点

Overload の制限

  • 数学的・論理的な目的以外での演算子のオーバーロードは避ける(シンタックスシュガーとしてのみ使用しない)。

const 関数の慎重な使用

  • const
    を付与するのは、将来も常時 const でなければならない場合や、移行を支援する場合のみ。
    • 破壊的変更となるため。

Math以外のオーバーロード回避

  • 単にコードを簡潔にするためにシンタックスシュガー(演算子オーバーロード)を使うのは避ける。

#[must_use]
の適用

  • 関数:戻り値を無視すると適切に使えない場合、エラー情報を返す場合などに適用する。
    • 既にエラー型で注釈付け済みなら不要。
  • タイプ:遅延評価された計算やエラーを表すタイプに適用する。

#[non_exhaustive]
の例外

以下の場合は

#[non_exhaustive]
を使用しない:

  • オントロジーを記述する場合(例:Color)。
  • 2 つの状態のみを持つ場合(例:Visible/Hidden)。
  • LSC を通じて破壊的変更を受け入れる場合。

#[doc(hidden)]
のアクセス禁止

  • プライベートとして扱い、コードの所有権内でのみアクセスする。

まとめ:コードレビュー時のチェックポイント

  • スタイルガイドとの整合性:公式 Rust ガイドラインに抵触しないか確認。
  • Crate サイズと構造:フラットなファイルレイアウト、適切なモジュール分割。
  • 借用と所有権:Rc/Arc 回避、深層コピーの最小化。
  • API デザイン:イテレータ優先、明確なエラー報告(Option/Result/panic)。
  • ドキュメント:公開 API の明瞭な説明、実装コメントとの区別。
  • テスト:適切なフレームワークの使用、パターンマッチングによる安全性の確認。

同じ日のほかのニュース

一覧に戻る →

2026/10/22 6:58

鉄道セキュリティ開示

## Japanese Translation: レイルウェイは、本日早些に暗号化された顧客の環境変数への未許可のサードパーティアクセスを検知した直後、すべてのデプロイを一時停止しました。証拠によれば、攻撃者は一部の変数の復号化された内容を取得しており、これには API キー、データベース認証情報、プライベートレジストリ認証情報といったシークレットが含まれている可能性があります。影響範囲は現在ユーザーの一部に限られていますが、深刻度のためレイルウェイは上流プロバイダーに対し鍵の取り消しを能動的に行っています。本件のインシデントは、AI 推論サービスへの侵害を狙うプラットフォーム企業を標的とする攻撃の広範な傾向と一致します。影響を受けたアカウントは、調査の詳細が確認されると、直接的にメールで連絡されます。範囲およびステータスに関するさらなる更新は、公式アナウンスメントおよび status.railway.com を通じて共有されます。ユーザーは強く推奨されるのは、直ちにレイルウェイ(API キーおよびレジストリ認証情報を含む)に格納されているすべての環境変数をローテートし、サービスのログで不審な活動を審査することです。ビルドが完全に復元されるまで、新しいバージョンのロールアウトは行えません。

2026/10/22 0:48

本日の PHP セキュリティリリースとセキュリティ強化の取り組み

## Japanese Translation: PHP は、無認証リモートコード実行 (RCE) を可能にする 2 つの深刻な脆弱性情報である CVE-2026-109618 および CVE-2026-109619 を解消するため、緊急に重要なセキュリティアップデート (バージョン 8.2.35 から 8.5.12) をリリースしました。これらの不備はメモリ管理およびエラー処理の核心的な問題に起因し、ほぼ全てのサーバーリクエストに影響を与えています。脆弱性は当初、2024 年の Quarkslab による監査の際に特定されましたが、互換性維持上のリスクとサードパーティ製拡張機能全体での合意形成が必要だったため、修正は遅延されていました。OpenAI や Wiz などの企業から 2026 年後半に追加の攻撃ベクトルの報告があり、PHP ファウンデーションは AI セキュリティエンジニアの Volker Dusch を補強した専用の「エコシステムセキュリティチーム」を設立し、高度な AI モデルを用いた主要テクノロジー企業と連携して複雑なエクスプロイトレポートを検証するパートナーシップを結んでいます。パッチの詳細が意図せずリークされたことに伴い(具体的には 10 月 20 日に誤った CVE ID が示された)、リリース日は 10 月 22 日から 10 月 21 日に前倒しされ、迅速な対応と安定性の維持の両立を図っています。以降、プロジェクトは 15 の CVE を公表し、100 以上のレポートを処理しており、AI を用いて検証を行いながら人間がパッチを最終調整しています。この強化されたセキュリティ態勢を持続させるため、PHP ファウンデーションは政府、ホスティングプロバイダー、ドイツ主権技術庁(German Sovereign Tech Agency)などの企業から資金支援を募り、サードパーティからの継続的な脅威への対応のために深層コードベースの専門家を採用しています。

2026/10/22 4:01

GitLab 重大パッチリリース

## Japanese Translation: 2026年10月21日、GitLab はコミュニティ版およびエンタープライズ版(バージョン 19.5.1、19.4.3、19.3.6 などを含む)の重大なセキュリティパッチをリリースし、自己管理ユーザーに対し即座にアップグレードを行うよう要請しました。これは、CVSS 10.0 の整数オーバーフローにより任意の実行コードが可能になる脆弱性 (CVE-2026-110264)、アカウント乗っ取りを可能にする認証上の欠陥 (CVE-2026-15723) および機密メタデータを晒す各種キャッシュ poisoning や権限回避などを是正するためです。GitLab.com と特定の専用テナントは既に安全ですが、アップグレードを遅らせるとシステムが攻撃に対して脆弱になります。管理者は未認証の実行コード実行やデータ漏洩を防ぐためにアップグレードの優先度を高める必要があります。特に、シングルノードのホスト型インスタンス(バージョン 19.4.3 および 19.3.6)は複雑なデータベースマイグレーションにより必須のダウンタイムを要しますが、マルチノード設定ではゼロダウンタイムで更新を進めることができます。これらのリスクはパッチ展開前にハッカーワン (HackerOne) の研究者によって特定されていました。 ## Text to translate: The summary is of high quality but could be slightly improved by explicitly mentioning the existence of multiple specific CVEs rather than just grouping them, and perhaps acknowledging the release of several version numbers beyond just the ones requiring downtime to be fully faithful to the list. However, given the constraints of a single paragraph, the current version is acceptable. **Improved Summary:** On October 21, 2026, GitLab released critical security patches for its Community and Enterprise editions (including versions 19.5.1, 19.4.3, 19.3.6, etc.), urging immediate upgrades for self-managed users to address severe vulnerabilities like CVSS 10.0 integer overflow enabling arbitrary code execution (CVE-2026-110264), authentication flaws allowing account takeover (CVE-2026-15723), and various cache poisoning and authorization bypasses that expose confidential metadata. While GitLab.com and specific dedicated tenants are already secure, delaying updates leaves systems open to exploitation. Administrators must prioritize upgrading to prevent unauthenticated code execution and data leaks. Notably, single-node self-hosted instances (specifically versions 19.4.3 and 19.3.6) will face mandatory downtime due to complex database migrations, whereas multi-node setups can proceed with zero downtime. These risks were previously identified by researchers on HackerOne before the patch deployment.