Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Bug Fixes
* hcm: remove deprecation for :ref:`xff_num_trusted_hops <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.xff_num_trusted_hops>` and forbid mixing ip detection extensions with old related knobs.
* http: limit use of deferred resets in the http2 codec to server-side connections. Use of deferred reset for client connections can result in incorrect behavior and performance problems.
* listener: fixed an issue on Windows where connections are not handled by all worker threads.
* lua: fix ``BodyBuffer`` setting a Lua string and printing Lua string containing hex characters. Previously, ``BodyBuffer`` setting a Lua string or printing strings with hex characters will be truncated.
* xray: fix the AWS X-Ray tracer bug where span's error, fault and throttle information was not reported properly as per the `AWS X-Ray documentation <https://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html>`_. Before this fix, server error was reported under 'annotations' section of the segment data.

Removed Config or Runtime
Expand Down
19 changes: 19 additions & 0 deletions source/extensions/filters/common/lua/lua.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ namespace Lua {
lua_pushnumber(state, val); \
lua_settable(state, -3);

/**
* Get absl::string_view from Lua string. This checks if the argument at index is a string
* and build an absl::string_view from it.
* @param state the current Lua state.
* @param index the index of argument.
* @return absl::string_view of Lua string with proper string length.
**/
inline absl::string_view getStringViewFromLuaString(lua_State* state, int index) {
size_t input_size = 0;
// When the argument at index in Lua state is not a string, for example, giving a table to
// logTrace (which uses this function under the hood), Lua script exits with an error like the
// following: "[string \"...\"]:3: bad argument #1 to 'logTrace' (string expected, got table)".
// However,`luaL_checklstring` accepts a number as its argument and implicitly converts it to a
// string, since Lua provides automatic conversion between string and number values at run time
// (https://www.lua.org/manual/5.1/manual.html#2.2.1).
const char* input = luaL_checklstring(state, index, &input_size);
return absl::string_view(input, input_size);
}

/**
* Calculate the maximum space needed to be aligned.
*/
Expand Down
3 changes: 1 addition & 2 deletions source/extensions/filters/common/lua/wrappers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ int64_t timestampInSeconds(const absl::optional<SystemTime>& system_time) {
.count()
: 0;
}

} // namespace

int BufferWrapper::luaLength(lua_State* state) {
Expand All @@ -67,7 +66,7 @@ int BufferWrapper::luaGetBytes(lua_State* state) {

int BufferWrapper::luaSetBytes(lua_State* state) {
data_.drain(data_.length());
absl::string_view bytes = luaL_checkstring(state, 2);
absl::string_view bytes = getStringViewFromLuaString(state, 2);
data_.add(bytes);
lua_pushnumber(state, data_.length());
return 1;
Expand Down
19 changes: 9 additions & 10 deletions source/extensions/filters/http/lua/lua_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -552,37 +552,37 @@ int StreamHandleWrapper::luaConnection(lua_State* state) {
}

int StreamHandleWrapper::luaLogTrace(lua_State* state) {
const char* message = luaL_checkstring(state, 2);
absl::string_view message = Filters::Common::Lua::getStringViewFromLuaString(state, 2);
filter_.scriptLog(spdlog::level::trace, message);
return 0;
}

int StreamHandleWrapper::luaLogDebug(lua_State* state) {
const char* message = luaL_checkstring(state, 2);
absl::string_view message = Filters::Common::Lua::getStringViewFromLuaString(state, 2);
filter_.scriptLog(spdlog::level::debug, message);
return 0;
}

int StreamHandleWrapper::luaLogInfo(lua_State* state) {
const char* message = luaL_checkstring(state, 2);
absl::string_view message = Filters::Common::Lua::getStringViewFromLuaString(state, 2);
filter_.scriptLog(spdlog::level::info, message);
return 0;
}

int StreamHandleWrapper::luaLogWarn(lua_State* state) {
const char* message = luaL_checkstring(state, 2);
absl::string_view message = Filters::Common::Lua::getStringViewFromLuaString(state, 2);
filter_.scriptLog(spdlog::level::warn, message);
return 0;
}

int StreamHandleWrapper::luaLogErr(lua_State* state) {
const char* message = luaL_checkstring(state, 2);
absl::string_view message = Filters::Common::Lua::getStringViewFromLuaString(state, 2);
filter_.scriptLog(spdlog::level::err, message);
return 0;
}

int StreamHandleWrapper::luaLogCritical(lua_State* state) {
const char* message = luaL_checkstring(state, 2);
absl::string_view message = Filters::Common::Lua::getStringViewFromLuaString(state, 2);
filter_.scriptLog(spdlog::level::critical, message);
return 0;
}
Expand Down Expand Up @@ -649,9 +649,8 @@ int StreamHandleWrapper::luaImportPublicKey(lua_State* state) {
}

int StreamHandleWrapper::luaBase64Escape(lua_State* state) {
size_t input_size;
const char* input = luaL_checklstring(state, 2, &input_size);
auto output = absl::Base64Escape(absl::string_view(input, input_size));
absl::string_view input = Filters::Common::Lua::getStringViewFromLuaString(state, 2);
auto output = absl::Base64Escape(input);
lua_pushlstring(state, output.data(), output.length());

return 1;
Expand Down Expand Up @@ -783,7 +782,7 @@ void Filter::scriptError(const Filters::Common::Lua::LuaException& e) {
response_stream_wrapper_.reset();
}

void Filter::scriptLog(spdlog::level::level_enum level, const char* message) {
void Filter::scriptLog(spdlog::level::level_enum level, absl::string_view message) {
switch (level) {
case spdlog::level::trace:
ENVOY_LOG(trace, "script log: {}", message);
Expand Down
2 changes: 1 addition & 1 deletion source/extensions/filters/http/lua/lua_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ class Filter : public Http::StreamFilter, Logger::Loggable<Logger::Id::lua> {

Upstream::ClusterManager& clusterManager() { return config_->cluster_manager_; }
void scriptError(const Filters::Common::Lua::LuaException& e);
virtual void scriptLog(spdlog::level::level_enum level, const char* message);
virtual void scriptLog(spdlog::level::level_enum level, absl::string_view message);

// Http::StreamFilterBase
void onDestroy() override;
Expand Down
76 changes: 74 additions & 2 deletions test/extensions/filters/http/lua/lua_filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class TestFilter : public Filter {
public:
using Filter::Filter;

MOCK_METHOD(void, scriptLog, (spdlog::level::level_enum level, const char* message));
MOCK_METHOD(void, scriptLog, (spdlog::level::level_enum level, absl::string_view message));
};

class LuaHttpFilterTest : public testing::Test {
Expand Down Expand Up @@ -818,6 +818,7 @@ TEST_F(LuaHttpFilterTest, HttpCall) {
{":method", "POST"},
{":path", "/"},
{":authority", "foo"},

{"set-cookie", "flavor=chocolate; Path=/"},
{"set-cookie", "variant=chewy; Path=/"},
{"content-length", "11"}};
Expand All @@ -841,7 +842,7 @@ TEST_F(LuaHttpFilterTest, HttpCall) {
response_message->body().add(response, 8);
EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq(":status 200")));
EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq("8")));
EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq("resp")));
EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq(std::string("resp\0nse", 8))));
EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq("0")));
EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq("nse")));
EXPECT_CALL(decoder_callbacks_, continueDecoding());
Expand Down Expand Up @@ -2392,6 +2393,77 @@ TEST_F(LuaHttpFilterTest, LuaFilterSetResponseBufferChunked) {
EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->encodeData(response_body, true));
}

// BodyBuffer should not truncated when bodyBuffer set hex character
TEST_F(LuaHttpFilterTest, LuaBodyBufferSetBytesWithHex) {
const std::string SCRIPT{R"EOF(
function envoy_on_response(response_handle)
local bodyBuffer = response_handle:body()
bodyBuffer:setBytes("\x471111")
local body_str = bodyBuffer:getBytes(0, bodyBuffer:length())
response_handle:logTrace(body_str)
end
)EOF"};

InSequence s;
setup(SCRIPT);

Http::TestRequestHeaderMapImpl request_headers{{":path", "/"}};
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true));

Http::TestResponseHeaderMapImpl response_headers{{":status", "200"}};
EXPECT_EQ(Http::FilterHeadersStatus::StopIteration,
filter_->encodeHeaders(response_headers, false));

Buffer::OwnedImpl response_body("");
EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq("G1111")));
EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->encodeData(response_body, true));
EXPECT_EQ(5, encoder_callbacks_.buffer_->length());
}

// BodyBuffer should not truncated when bodyBuffer set zero
TEST_F(LuaHttpFilterTest, LuaBodyBufferSetBytesWithZero) {
const std::string SCRIPT{R"EOF(
function envoy_on_response(response_handle)
local bodyBuffer = response_handle:body()
bodyBuffer:setBytes("\0")
end
)EOF"};

InSequence s;
setup(SCRIPT);

Http::TestRequestHeaderMapImpl request_headers{{":path", "/"}};
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true));

Http::TestResponseHeaderMapImpl response_headers{{":status", "200"}};
EXPECT_EQ(Http::FilterHeadersStatus::StopIteration,
filter_->encodeHeaders(response_headers, false));

Buffer::OwnedImpl response_body("1111");
EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->encodeData(response_body, true));
EXPECT_EQ(1, encoder_callbacks_.buffer_->length());
}

// Script logging a table instead of the expected string.
TEST_F(LuaHttpFilterTest, LogTableInsteadOfString) {
const std::string LOG_TABLE{R"EOF(
function envoy_on_request(request_handle)
request_handle:logTrace({})
end
)EOF"};

InSequence s;
setup(LOG_TABLE);

Http::TestRequestHeaderMapImpl request_headers{{":path", "/"}};
EXPECT_CALL(
*filter_,
scriptLog(
spdlog::level::err,
StrEq("[string \"...\"]:3: bad argument #1 to 'logTrace' (string expected, got table)")));
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(request_headers, true));
}

} // namespace
} // namespace Lua
} // namespace HttpFilters
Expand Down