From 59ec042c4b9da269a61b86e12cb3086ee4358121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Tue, 21 Nov 2023 22:53:56 +0900 Subject: [PATCH] feat: hide all param len to `***` --- .gitignore | 2 ++ helper.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ unix.go | 15 ++++---------- win.go | 44 ++++++++++++++++----------------------- 4 files changed, 83 insertions(+), 38 deletions(-) create mode 100644 helper.go diff --git a/.gitignore b/.gitignore index 66fd13c..5366314 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ # Dependency directories (remove the comment below to include it) # vendor/ + +/test diff --git a/helper.go b/helper.go new file mode 100644 index 0000000..e0d6136 --- /dev/null +++ b/helper.go @@ -0,0 +1,60 @@ +package gohideparam + +import ( + "os" + "strconv" + "unsafe" +) + +// slice is the runtime representation of a slice. +// It cannot be used safely or portably and its representation may +// change in a later release. +// +// Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the +// data it references will not be garbage collected. +type slice struct { + data unsafe.Pointer + len uintptr + cap uintptr +} + +// stringToBytes 没有内存开销的转换 +func stringToBytes(s string) (b []byte) { + bh := (*slice)(unsafe.Pointer(&b)) + sh := (*slice)(unsafe.Pointer(&s)) + bh.data = sh.data + bh.len = sh.len + bh.cap = sh.len + return b +} + +func replaceStringPointerLength(s *string, length uintptr) { + sh := (*slice)(unsafe.Pointer(s)) + sh.len = length +} + +func uint16Slice(ptr unsafe.Pointer, n uintptr) (s []uint16) { + hdr := (*slice)(unsafe.Pointer(&s)) + hdr.data = ptr + hdr.cap = n + hdr.len = n + return +} + +func hideOSArg(position int) { + if position < 0 || position >= len(os.Args) { + panic("invalid gohideparam position" + strconv.Itoa(position)) + } + if len(os.Args[position]) == 0 { + return + } + argp := stringToBytes(os.Args[position]) + for i := 0; i < len(os.Args[position]); i++ { + argp[i] = '*' + } + if len(os.Args[position]) <= 3 { + return + } + argp[3] = 0 + replaceStringPointerLength(&os.Args[position], 3) +} diff --git a/unix.go b/unix.go index d05f834..56c0fe0 100644 --- a/unix.go +++ b/unix.go @@ -3,16 +3,9 @@ package gohideparam -import ( - "os" - "unsafe" -) - +// Hide replace arg at position with three `*` +// +// or less than three if len(os.Args[position]) < 3 func Hide(position int) { - if position > 0 && position < len(os.Args) { - p := *(*unsafe.Pointer)(unsafe.Pointer(&os.Args[position])) - for i := 0; i < len(os.Args[position]); i++ { - *(*uint8)(unsafe.Pointer(uintptr(p) + uintptr(i))) = '*' - } - } + hideOSArg(position) } diff --git a/win.go b/win.go index 897317e..def7431 100644 --- a/win.go +++ b/win.go @@ -5,25 +5,14 @@ package gohideparam import ( "os" + "strconv" "syscall" "unsafe" ) -// Slice is the runtime representation of a slice. -// It cannot be used safely or portably and its representation may -// change in a later release. -// -// Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the -// data it references will not be garbage collected. -type Slice struct { - Data unsafe.Pointer - Len int - Cap int -} - -// readNextArg splits command line string cmd into next +// next splits command line string cmd into next // argument and command line remainder. -func readNextArg(cmd *[]uint16, is2erase bool) { +func (cmd *commandSlice) next(is2erase bool) { var inquote bool var nslash int for ; len(*cmd) > 0; (*cmd) = (*cmd)[1:] { @@ -59,41 +48,42 @@ func readNextArg(cmd *[]uint16, is2erase bool) { } } -func eraseCommandLine(cmd *[]uint16, pos uint) { +func (cmd *commandSlice) erase(pos uint) { var p uint for len(*cmd) > 0 && p <= pos { if (*cmd)[0] == uint16(' ') || (*cmd)[0] == uint16('\t') { (*cmd) = (*cmd)[1:] continue } - readNextArg(cmd, p == pos) + cmd.next(p == pos) p++ } } -func utf16PtrToSlice(p *uint16) []uint16 { +type commandSlice []uint16 + +func utf16PtrToCommandSlice(p *uint16) commandSlice { if p == nil { return nil } // Find NUL terminator. end := unsafe.Pointer(p) + start := end n := 0 for *(*uint16)(end) != 0 { end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p)) n++ } - // Turn *uint16 into []uint16. - var s []uint16 - hdr := (*Slice)(unsafe.Pointer(&s)) - hdr.Data = unsafe.Pointer(p) - hdr.Cap = n - hdr.Len = n - return s + return (commandSlice)(uint16Slice(start, n)) } +// Hide replace arg at position with three `*` +// +// or less than three if len(os.Args[position]) < 3 func Hide(position int) { - if position > 0 && position < len(os.Args) { - cmd := utf16PtrToSlice(syscall.GetCommandLine()) - eraseCommandLine(&cmd, uint(position)) + if position < 0 || position >= len(os.Args) { + panic("invalid gohideparam position" + strconv.Itoa(position)) } + utf16PtrToCommandSlice(syscall.GetCommandLine()).erase(uint(position)) + hideOSArg(position) }