C++ で環境変数を取得する

胡金庫 2023年10月12日
  1. C++ の環境変数にアクセスするには std::getenv 関数を使用する
  2. 環境変数の有効な値を検証するためにカスタムチェックルーチンを使用する
C++ で環境変数を取得する

この記事では、C++ で環境変数を取得する方法をいくつか説明します。

C++ の環境変数にアクセスするには std::getenv 関数を使用する

getenv は C 標準ライブラリで実装されている POSIX 準拠の関数であり、C++ のソースファイルから <cstdlib> ヘッダを用いてインポートすることができます。この関数は文字列を唯一の引数として受け取り、それと等しい環境変数名を検索します。

環境変数は通常、すべて大文字で表現されるが、getenv では、プログラム環境で定義されていても変数名と一致しないため、引数文字列に小文字を入れないようにする必要があります。この関数は、対応する変数の値が格納されている char* 型を返します。

プログラムがその場所を変更しないようにする必要があるため、getenv の戻り値を const char* 変数に代入していることに注意してください。

#include <cstdlib>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::getenv;
using std::string;

const char *ENV_VAR = "HOME";

int main() {
  const char *tmp = getenv("HOME");
  string env_var(tmp ? tmp : "");
  if (env_var.empty()) {
    cerr << "[ERROR] No such variable found!" << endl;
    exit(EXIT_FAILURE);
  }

  cout << "HOME : " << env_var << endl;

  exit(EXIT_SUCCESS);
}

出力:

HOME : /home/username

また、getenv 関数から返された値を std::string コンストラクタに直接渡さないことも重要です。これは、getenv 関数が環境変数の計算に失敗したときにセグメンテーション違反をスローする可能性があるためです。

この問題は、std::char_traits::length() 関数を呼び出す std::string コンストラクタのコードの実装の中で発生しています。後者の関数は、引数に nullptr を渡すと未定義の振る舞いをします。このように、環境変数が見つからなかった場合に getenvnullptr を返すことができ、それを string のコンストラクタに渡すと誤ったコードが生成されてしまうというシナリオがあります。

#include <cstdlib>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::getenv;
using std::string;

const char *ENV_VAR = "HOME";

int main() {
  // Erroneous
  string env_var(getenv("HOME"));
  if (env_var.empty()) {
    cerr << "[ERROR] No such variable found!" << endl;
    exit(EXIT_FAILURE);
  }

  cout << "HOME : " << env_var << endl;

  exit(EXIT_SUCCESS);
}

環境変数の有効な値を検証するためにカスタムチェックルーチンを使用する

環境変数にアクセスする際に最も危険な落とし穴の一つは、取得した値を検証することです。これらの変数は、攻撃者によってプログラムの範囲外で操作される可能性があることに注意してください。したがって、正しく安全なプログラムの実行を保証するために、これらの値の追加のサニタイズが必要です。

これらのチェックルーチンは、ほとんどがプログラムに依存しており、ケースごとに異なる処理を行う必要があります。以下の例では、文字列の値にスペースがあってはならないと仮定し、スペースがある場合には最初のスペース文字の前の部分文字列を抽出するシナリオを示しています。このようにして、システム環境からの不規則な入力値を回避することができます。なお、std::find アルゴリズムは string の中の文字を検索するために利用され、指定された char が見つからなかった場合は string::npos を返します。

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::find;
using std::getenv;
using std::string;

const char *ENV_VAR = "HOME";

int main() {
  const char *tmp = getenv(ENV_VAR);
  string env_var(tmp ? tmp : "");
  if (env_var.empty()) {
    cerr << "[ERROR] No such variable found!" << endl;
    exit(EXIT_FAILURE);
  }

  // Env Variable Value Sanitization
  int pos = env_var.find(' ');
  if (pos != string::npos) env_var = env_var.substr(0, pos);

  cout << "HOME : " << env_var << endl;

  exit(EXIT_SUCCESS);
}
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook