You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2020/09/10 08:49:26 UTC
[apisix] branch master updated: chore: add string utility for
simplicity and correctness (#2181)
This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 37817e4 chore: add string utility for simplicity and correctness (#2181)
37817e4 is described below
commit 37817e419827889be3358bfc538aa6046becac58
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Thu Sep 10 16:49:20 2020 +0800
chore: add string utility for simplicity and correctness (#2181)
* chore: add string utility for simplicity and correctness
* localize error
* correct the misuse string.find
Co-authored-by: YuanSheng Wang <me...@gmail.com>
---
apisix/admin/ssl.lua | 3 +-
apisix/core.lua | 1 +
apisix/core/string.lua | 68 ++++++++++++++++
apisix/http/router/radixtree_sni.lua | 2 +-
t/core/string.t | 145 +++++++++++++++++++++++++++++++++++
5 files changed, 216 insertions(+), 3 deletions(-)
diff --git a/apisix/admin/ssl.lua b/apisix/admin/ssl.lua
index f102f27..c86a172 100644
--- a/apisix/admin/ssl.lua
+++ b/apisix/admin/ssl.lua
@@ -18,7 +18,6 @@ local core = require("apisix.core")
local tostring = tostring
local aes = require "resty.aes"
local ngx_encode_base64 = ngx.encode_base64
-local str_find = string.find
local type = type
local assert = assert
@@ -74,7 +73,7 @@ local function aes_encrypt(origin)
local aes_128_cbc_with_iv = (type(iv)=="string" and #iv == 16) and
assert(aes:new(iv, nil, aes.cipher(128, "cbc"), {iv=iv})) or nil
- if aes_128_cbc_with_iv ~= nil and str_find(origin, "---") then
+ if aes_128_cbc_with_iv ~= nil and core.string.has_prefix(origin, "---") then
local encrypted = aes_128_cbc_with_iv:encrypt(origin)
if encrypted == nil then
core.log.error("failed to encrypt key[", origin, "] ")
diff --git a/apisix/core.lua b/apisix/core.lua
index 2d3ca2e..da94af4 100644
--- a/apisix/core.lua
+++ b/apisix/core.lua
@@ -34,6 +34,7 @@ return {
response = require("apisix.core.response"),
lrucache = require("apisix.core.lrucache"),
schema = require("apisix.schema_def"),
+ string = require("apisix.core.string"),
ctx = require("apisix.core.ctx"),
timer = require("apisix.core.timer"),
id = require("apisix.core.id"),
diff --git a/apisix/core/string.lua b/apisix/core/string.lua
new file mode 100644
index 0000000..952152a
--- /dev/null
+++ b/apisix/core/string.lua
@@ -0,0 +1,68 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements. See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local error = error
+local type = type
+local str_find = string.find
+local ffi = require("ffi")
+local C = ffi.C
+local ffi_cast = ffi.cast
+
+
+ffi.cdef[[
+ int memcmp(const void *s1, const void *s2, size_t n);
+]]
+
+
+local _M = {
+ version = 0.1,
+}
+
+
+setmetatable(_M, {__index = string})
+
+
+-- find a needle from a haystack in the plain text way
+function _M.find(haystack, needle, from)
+ return str_find(haystack, needle, from or 1, true)
+end
+
+
+function _M.has_prefix(s, prefix)
+ if type(s) ~= "string" or type(prefix) ~= "string" then
+ error("unexpected type: s:" .. type(s) .. ", prefix:" .. type(prefix))
+ end
+ if #s < #prefix then
+ return false
+ end
+ local rc = C.memcmp(s, prefix, #prefix)
+ return rc == 0
+end
+
+
+function _M.has_suffix(s, suffix)
+ if type(s) ~= "string" or type(suffix) ~= "string" then
+ error("unexpected type: s:" .. type(s) .. ", suffix:" .. type(suffix))
+ end
+ if #s < #suffix then
+ return false
+ end
+ local rc = C.memcmp(ffi_cast("char *", s) + #s - #suffix, suffix, #suffix)
+ return rc == 0
+end
+
+
+return _M
diff --git a/apisix/http/router/radixtree_sni.lua b/apisix/http/router/radixtree_sni.lua
index be24f52..4f54171 100644
--- a/apisix/http/router/radixtree_sni.lua
+++ b/apisix/http/router/radixtree_sni.lua
@@ -96,7 +96,7 @@ local function create_router(ssl_items)
-- decrypt private key
if aes_128_cbc_with_iv ~= nil and
- not str_find(ssl.value.key, "---") then
+ not core.string.has_prefix(ssl.value.key, "---") then
local decrypted = aes_128_cbc_with_iv:decrypt(ngx_decode_base64(ssl.value.key))
if decrypted == nil then
core.log.error("decrypt ssl key failed. key[", ssl.value.key, "] ")
diff --git a/t/core/string.t b/t/core/string.t
new file mode 100644
index 0000000..0e196e1
--- /dev/null
+++ b/t/core/string.t
@@ -0,0 +1,145 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX 'no_plan';
+
+repeat_each(2);
+no_long_string();
+no_root_location();
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: find
+--- config
+ location /t {
+ content_by_lua_block {
+ local encode = require "cjson".encode
+ local str = require("apisix.core.string")
+ local cases = {
+ {"xx", "", true},
+ {"xx", "x", true},
+ {"", "x", false},
+ {"", "", true},
+ {"", 0, false},
+ {0, "x", false},
+ {"a[", "[", true},
+
+ {"[a", "[", false, 2},
+ {"[a", "[", false, 3},
+ {"[a", "[", true, 1},
+ }
+ for _, case in ipairs(cases) do
+ local ok, idx = pcall(str.find, case[1], case[2], case[4])
+ if not ok then
+ if case[3] == true then
+ ngx.log(ngx.ERR, "unexpected error: ", idx,
+ " ", encode(case))
+ end
+ else
+ if case[3] ~= (idx ~= nil) then
+ ngx.log(ngx.ERR, "unexpected res: ", idx,
+ " ", encode(case))
+ end
+ end
+ end
+ }
+ }
+--- request
+GET /t
+--- no_error_log
+[error]
+
+
+
+=== TEST 2: prefix
+--- config
+ location /t {
+ content_by_lua_block {
+ local encode = require "cjson".encode
+ local str = require("apisix.core.string")
+ local cases = {
+ {"xx", "", true},
+ {"xx", "x", true},
+ {"", "x", false},
+ {"", "", true},
+ {"", 0, false},
+ {0, "x", false},
+ {"a[", "[", false},
+ {"[a", "[", true},
+ {"[a", "[b", false},
+ }
+ for _, case in ipairs(cases) do
+ local ok, res = pcall(str.has_prefix, case[1], case[2])
+ if not ok then
+ if case[3] == true then
+ ngx.log(ngx.ERR, "unexpected error: ", res,
+ " ", encode(case))
+ end
+ else
+ if case[3] ~= res then
+ ngx.log(ngx.ERR, "unexpected res: ", res,
+ " ", encode(case))
+ end
+ end
+ end
+ }
+ }
+--- request
+GET /t
+--- no_error_log
+[error]
+
+
+
+=== TEST 3: suffix
+--- config
+ location /t {
+ content_by_lua_block {
+ local encode = require "cjson".encode
+ local str = require("apisix.core.string")
+ local cases = {
+ {"xx", "", true},
+ {"xx", "x", true},
+ {"", "x", false},
+ {"", "", true},
+ {"", 0, false},
+ {0, "x", false},
+ {"a[", "[", true},
+ {"[a", "[", false},
+ {"[a", "[b", false},
+ }
+ for _, case in ipairs(cases) do
+ local ok, res = pcall(str.has_suffix, case[1], case[2])
+ if not ok then
+ if case[3] == true then
+ ngx.log(ngx.ERR, "unexpected error: ", res,
+ " ", encode(case))
+ end
+ else
+ if case[3] ~= res then
+ ngx.log(ngx.ERR, "unexpected res: ", res,
+ " ", encode(case))
+ end
+ end
+ end
+ }
+ }
+--- request
+GET /t
+--- no_error_log
+[error]