问题描述
cargs.Init 在加解密参数时,使用 strings.Join(args, " ") 和 strings.Split(output, " ") 来拼接 / 拆分参数。当某个参数值内部包含空格时,加密再解密后,该参数会被错误地拆成多个参数,参数个数和内容都无法还原。
复现步骤
- 使用 cargs 编译一个简单的程序:
package main
import (
"fmt"
"os"
"github.com/12end/cargs"
)
func main() {
cargs.Init([]byte("cargsRandomKey"), "getarg")
fmt.Printf("args = %#v\n", os.Args[1:])
}
- 生成加密参数,传入一个带空格的值:
./main getarg --name "hello world"
# 输出: cargs output: <base64>
- 用该加密参数运行:
期望行为
程序看到的参数应为:
args = []string{"--name", "hello world"}
即与加密前完全一致,hello world 是一个完整的参数值。
实际行为
程序看到的参数变成了:
args = []string{"--name", "hello", "world"}
hello world 被拆成了两个独立参数,原本的参数语义被破坏(--name 只取到 hello,多出一个未知的 world)。
原因分析
cargs.go 中:
// 加密分支
input := []byte(strings.Join(os.Args[2:], " ")) // 用空格把多个参数拼成一个字符串
// 解密分支
os.Args = append(os.Args[:1], strings.Split(string(output), " ")...) // 再用空格切回去
Join 时无法区分「参数之间的分隔空格」和「参数值内部的空格」,Split 时一律按空格切开,因此参数值内部的空格会被当作参数分隔符。同理,连续空格也会产生空字符串参数(strings.Split("a b", " ") → ["a", "", "b"])。
建议修复方向
不要用单一分隔符 join/split 来序列化参数切片,可采用任一可逆的编码方式,例如:
- 对每个参数单独 base64 编码后再用空格连接,解密后再逐个 base64 解码;
- 或用
encoding/gob / encoding/json 序列化整个 []string;
- 或使用一个不可能出现在 base64 输出里的分隔符(如换行符
\n)逐项拼接,并保留个数信息。
环境
- OS:macOS(其他平台应同样复现)
- Go 版本:go 1.21
- cargs 版本:master(最新)
问题描述
cargs.Init在加解密参数时,使用strings.Join(args, " ")和strings.Split(output, " ")来拼接 / 拆分参数。当某个参数值内部包含空格时,加密再解密后,该参数会被错误地拆成多个参数,参数个数和内容都无法还原。复现步骤
期望行为
程序看到的参数应为:
即与加密前完全一致,
hello world是一个完整的参数值。实际行为
程序看到的参数变成了:
hello world被拆成了两个独立参数,原本的参数语义被破坏(--name只取到hello,多出一个未知的world)。原因分析
cargs.go中:Join 时无法区分「参数之间的分隔空格」和「参数值内部的空格」,Split 时一律按空格切开,因此参数值内部的空格会被当作参数分隔符。同理,连续空格也会产生空字符串参数(
strings.Split("a b", " ")→["a", "", "b"])。建议修复方向
不要用单一分隔符 join/split 来序列化参数切片,可采用任一可逆的编码方式,例如:
encoding/gob/encoding/json序列化整个[]string;\n)逐项拼接,并保留个数信息。环境