v3: Lua m.setvar() returns -1 on errors, so the script gets stack garbage

オープン 初心者向け
#3,731 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@fzipi がすでに取り組んでいます。

2026年11月1日 から。

  • #3732 @fzipi による — オープン

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
72/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
cpp, lua
領域
backend

調査の方向性

src/engine/lua.cc の Lua::setvar() から始めてください。ここでは3つのエラーパスが -1 を返しています(343行目、351行目、366行目付近)。C++ のローカル変数が存在する前に luaL_checkstring() を呼んでいる getvar() と比較してください。完了条件は、エラーパスが 0 を返す(または nil をプッシュして 1 を返す)こと、2つの luaL_checkstring() 呼び出しを std::string のローカル変数より前に移動すること、誤字を修正すること、そして2つの再現スクリプトを実行して返り値を検証する回帰テストを追加することです。

索引モデルが issue の本文から書いたものです。

説明

3.x bug

@airween, I found this while reviewing #3730. It's in the same file but a separate problem, so I'm filing it on its own.

Problem

Lua::setvar() (src/engine/lua.cc, v3/master 9d45c6d7) returns -1 on its three error paths:

  • line 343: wrong number of arguments;
  • line 351: luaL_checkstring() returned NULL;
  • line 366: no . in the name, so no collection.

A lua_CFunction must return the number of values it pushed onto the stack. Lua doesn't check for a negative count in release builds, so the call returns whatever happens to be on the stack.

Reproduction

I used two scripts run with exec: in phase 1 (macOS, Lua 5.5.1):

-- nodot.lua
function main()
    local r = m.setvar("novar", "x");
    m.log(4, "after setvar, got: " .. tostring(r));
    return nil;
end
-- onearg.lua
function main()
    local r = m.setvar("tx.a");
    m.log(4, "after setvar, got: " .. tostring(r));
    return nil;
end

Debug log:

[8] m.setvar: Must specify a collection using dot character - ie m.setvar(tx.myvar,mydata)
[4] after setvar, got: userdata: 0x16f5b2498
...
[8] m.setvar: Failed m.setvar funtion must has 2 arguments
[4] after setvar, got: [

In the first case the script gets back the __transaction pointer that setvar() pushed. In the second it gets a stray string. Nothing crashed here, but this is undefined behaviour, and the result depends on the Lua version and build.

A related, smaller point

luaL_checkstring() raises a Lua error, using longjmp with the usual C build of Lua, when an argument isn't a string, e.g. m.setvar("tx.a", {}). In setvar() that happens after the three std::string locals have been constructed, so their destructors are skipped. They're still empty at that point, so nothing leaks today, but it's fragile. getvar(), getvars() and log() call luaL_checkstring() before any C++ object exists, so they're fine.

Suggested fix
  • Return 0 (no results) on the three error paths, as log() does. Or, if a script should see the failure, push nil or false and return 1.
  • Move the two luaL_checkstring() calls before the std::string locals, as in getvar().
  • While there: fix the typo in the debug message ("funtion must has" → "function must have").

A regression case with the two scripts above, checking that m.setvar() returns nil (or false), would cover it.

主要言語
C++
スター
9.8k
フォーク
1.8k
平均マージ
1日 9時間
マージ済み PR(30日)
19

環境構築

  • Dockerfile・Docker Compose ファイルなし
  • プルリクエストのテンプレートあり
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

owasp-modsecurity/ModSecurity のほかの issue

owasp-modsecurity/ModSecurity の issue をすべて見る

似ている issue

C++ の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。