ldd: separate Parse from Exec and trim space
Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
This commit is contained in:
parent
22dfa73efe
commit
d41b9d2d9c
|
@ -90,9 +90,6 @@ func (p *Proxy) Start(ready chan error, output io.Writer, sandbox bool) error {
|
||||||
// xdb-dbus-proxy bin and dependencies
|
// xdb-dbus-proxy bin and dependencies
|
||||||
roBindTarget[path.Dir(toolPath)] = struct{}{}
|
roBindTarget[path.Dir(toolPath)] = struct{}{}
|
||||||
for _, ent := range proxyDeps {
|
for _, ent := range proxyDeps {
|
||||||
if ent == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if path.IsAbs(ent.Path) {
|
if path.IsAbs(ent.Path) {
|
||||||
roBindTarget[path.Dir(ent.Path)] = struct{}{}
|
roBindTarget[path.Dir(ent.Path)] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
26
ldd/error.go
26
ldd/error.go
|
@ -1,11 +1,27 @@
|
||||||
package ldd
|
package ldd
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
type EntryUnexpectedSegmentsError struct {
|
var (
|
||||||
Entry string
|
ErrUnexpectedSeparator = errors.New("unexpected separator")
|
||||||
|
ErrPathNotAbsolute = errors.New("path not absolute")
|
||||||
|
ErrBadLocationFormat = errors.New("bad location format")
|
||||||
|
ErrUnexpectedNewline = errors.New("unexpected newline")
|
||||||
|
)
|
||||||
|
|
||||||
|
type EntryUnexpectedSegmentsError string
|
||||||
|
|
||||||
|
func (e EntryUnexpectedSegmentsError) Is(err error) bool {
|
||||||
|
var eq EntryUnexpectedSegmentsError
|
||||||
|
if !errors.As(err, &eq) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return e == eq
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EntryUnexpectedSegmentsError) Error() string {
|
func (e EntryUnexpectedSegmentsError) Error() string {
|
||||||
return fmt.Sprintf("unexpected segments in entry %q", e.Entry)
|
return fmt.Sprintf("unexpected segments in entry %q", string(e))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package ldd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Exec(p string) ([]*Entry, error) {
|
||||||
|
t := exec.Command("ldd", p)
|
||||||
|
t.Stdout, t.Stderr = new(strings.Builder), os.Stderr
|
||||||
|
if err := t.Run(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Parse(t.Stdout.(fmt.Stringer))
|
||||||
|
}
|
28
ldd/ldd.go
28
ldd/ldd.go
|
@ -1,49 +1,31 @@
|
||||||
package ldd
|
package ldd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
ErrUnexpectedSeparator = errors.New("unexpected separator")
|
|
||||||
ErrPathNotAbsolute = errors.New("path not absolute")
|
|
||||||
ErrBadLocationFormat = errors.New("bad location format")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
Location uint64 `json:"location"`
|
Location uint64 `json:"location"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Exec(p string) ([]*Entry, error) {
|
func Parse(stdout fmt.Stringer) ([]*Entry, error) {
|
||||||
t := exec.Command("ldd", p)
|
payload := strings.Split(strings.TrimSpace(stdout.String()), "\n")
|
||||||
t.Stdout = new(strings.Builder)
|
|
||||||
t.Stderr = os.Stderr
|
|
||||||
|
|
||||||
if err := t.Run(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
out := t.Stdout.(fmt.Stringer).String()
|
|
||||||
payload := strings.Split(out, "\n")
|
|
||||||
|
|
||||||
result := make([]*Entry, len(payload))
|
result := make([]*Entry, len(payload))
|
||||||
|
|
||||||
for i, ent := range payload {
|
for i, ent := range payload {
|
||||||
if len(ent) == 0 {
|
if len(ent) == 0 {
|
||||||
continue
|
return nil, ErrUnexpectedNewline
|
||||||
}
|
}
|
||||||
|
|
||||||
segment := strings.SplitN(ent, " ", 5)
|
segment := strings.SplitN(ent, " ", 5)
|
||||||
|
|
||||||
|
// location index
|
||||||
var iL int
|
var iL int
|
||||||
|
|
||||||
switch len(segment) {
|
switch len(segment) {
|
||||||
|
@ -63,7 +45,7 @@ func Exec(p string) ([]*Entry, error) {
|
||||||
Path: segment[2],
|
Path: segment[2],
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, &EntryUnexpectedSegmentsError{ent}
|
return nil, EntryUnexpectedSegmentsError(ent)
|
||||||
}
|
}
|
||||||
|
|
||||||
if loc, err := parseLocation(segment[iL]); err != nil {
|
if loc, err := parseLocation(segment[iL]); err != nil {
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
package ldd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.ophivana.moe/cat/fortify/ldd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseError(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name, out string
|
||||||
|
wantErr error
|
||||||
|
}{
|
||||||
|
{"unexpected newline", `
|
||||||
|
/lib/ld-musl-x86_64.so.1 (0x7ff71c0a4000)
|
||||||
|
|
||||||
|
libzstd.so.1 => /usr/lib/libzstd.so.1 (0x7ff71bfd2000)
|
||||||
|
`, ldd.ErrUnexpectedNewline},
|
||||||
|
{"unexpected separator", `
|
||||||
|
libzstd.so.1 = /usr/lib/libzstd.so.1 (0x7ff71bfd2000)
|
||||||
|
`, ldd.ErrUnexpectedSeparator},
|
||||||
|
{"path not absolute", `
|
||||||
|
libzstd.so.1 => usr/lib/libzstd.so.1 (0x7ff71bfd2000)
|
||||||
|
`, ldd.ErrPathNotAbsolute},
|
||||||
|
{"unexpected segments", `
|
||||||
|
meow libzstd.so.1 => /usr/lib/libzstd.so.1 (0x7ff71bfd2000)
|
||||||
|
`, ldd.EntryUnexpectedSegmentsError("meow libzstd.so.1 => /usr/lib/libzstd.so.1 (0x7ff71bfd2000)")},
|
||||||
|
{"bad location format", `
|
||||||
|
libzstd.so.1 => /usr/lib/libzstd.so.1 7ff71bfd2000
|
||||||
|
`, ldd.ErrBadLocationFormat},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
stdout := new(strings.Builder)
|
||||||
|
stdout.WriteString(tc.out)
|
||||||
|
|
||||||
|
if _, err := ldd.Parse(stdout); !errors.Is(err, tc.wantErr) {
|
||||||
|
t.Errorf("Parse() error = %v, wantErr %v", err, tc.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
file, out string
|
||||||
|
want []*ldd.Entry
|
||||||
|
}{
|
||||||
|
{"musl /bin/kmod", `
|
||||||
|
/lib/ld-musl-x86_64.so.1 (0x7ff71c0a4000)
|
||||||
|
libzstd.so.1 => /usr/lib/libzstd.so.1 (0x7ff71bfd2000)
|
||||||
|
liblzma.so.5 => /usr/lib/liblzma.so.5 (0x7ff71bf9a000)
|
||||||
|
libz.so.1 => /lib/libz.so.1 (0x7ff71bf80000)
|
||||||
|
libcrypto.so.3 => /lib/libcrypto.so.3 (0x7ff71ba00000)
|
||||||
|
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7ff71c0a4000)`,
|
||||||
|
[]*ldd.Entry{
|
||||||
|
{"/lib/ld-musl-x86_64.so.1", "", 0x7ff71c0a4000},
|
||||||
|
{"libzstd.so.1", "/usr/lib/libzstd.so.1", 0x7ff71bfd2000},
|
||||||
|
{"liblzma.so.5", "/usr/lib/liblzma.so.5", 0x7ff71bf9a000},
|
||||||
|
{"libz.so.1", "/lib/libz.so.1", 0x7ff71bf80000},
|
||||||
|
{"libcrypto.so.3", "/lib/libcrypto.so.3", 0x7ff71ba00000},
|
||||||
|
{"libc.musl-x86_64.so.1", "/lib/ld-musl-x86_64.so.1", 0x7ff71c0a4000},
|
||||||
|
}},
|
||||||
|
{"glibc /nix/store/rc3n2r3nffpib2gqpxlkjx36frw6n34z-kmod-31/bin/kmod", `
|
||||||
|
linux-vdso.so.1 (0x00007ffed65be000)
|
||||||
|
libzstd.so.1 => /nix/store/80pxmvb9q43kh9rkjagc4h41vf6dh1y6-zstd-1.5.6/lib/libzstd.so.1 (0x00007f3199cd1000)
|
||||||
|
liblzma.so.5 => /nix/store/g78jna1i5qhh8gqs4mr64648f0szqgw4-xz-5.4.7/lib/liblzma.so.5 (0x00007f3199ca2000)
|
||||||
|
libc.so.6 => /nix/store/c10zhkbp6jmyh0xc5kd123ga8yy2p4hk-glibc-2.39-52/lib/libc.so.6 (0x00007f3199ab5000)
|
||||||
|
libpthread.so.0 => /nix/store/c10zhkbp6jmyh0xc5kd123ga8yy2p4hk-glibc-2.39-52/lib/libpthread.so.0 (0x00007f3199ab0000)
|
||||||
|
/nix/store/c10zhkbp6jmyh0xc5kd123ga8yy2p4hk-glibc-2.39-52/lib/ld-linux-x86-64.so.2 => /nix/store/c10zhkbp6jmyh0xc5kd123ga8yy2p4hk-glibc-2.39-52/lib64/ld-linux-x86-64.so.2 (0x00007f3199da5000)`,
|
||||||
|
[]*ldd.Entry{
|
||||||
|
{"linux-vdso.so.1", "", 0x00007ffed65be000},
|
||||||
|
{"libzstd.so.1", "/nix/store/80pxmvb9q43kh9rkjagc4h41vf6dh1y6-zstd-1.5.6/lib/libzstd.so.1", 0x00007f3199cd1000},
|
||||||
|
{"liblzma.so.5", "/nix/store/g78jna1i5qhh8gqs4mr64648f0szqgw4-xz-5.4.7/lib/liblzma.so.5", 0x00007f3199ca2000},
|
||||||
|
{"libc.so.6", "/nix/store/c10zhkbp6jmyh0xc5kd123ga8yy2p4hk-glibc-2.39-52/lib/libc.so.6", 0x00007f3199ab5000},
|
||||||
|
{"libpthread.so.0", "/nix/store/c10zhkbp6jmyh0xc5kd123ga8yy2p4hk-glibc-2.39-52/lib/libpthread.so.0", 0x00007f3199ab0000},
|
||||||
|
{"/nix/store/c10zhkbp6jmyh0xc5kd123ga8yy2p4hk-glibc-2.39-52/lib/ld-linux-x86-64.so.2", "/nix/store/c10zhkbp6jmyh0xc5kd123ga8yy2p4hk-glibc-2.39-52/lib64/ld-linux-x86-64.so.2", 0x00007f3199da5000},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.file, func(t *testing.T) {
|
||||||
|
stdout := new(strings.Builder)
|
||||||
|
stdout.WriteString(tc.out)
|
||||||
|
|
||||||
|
if got, err := ldd.Parse(stdout); err != nil {
|
||||||
|
t.Errorf("Parse() error = %v", err)
|
||||||
|
} else if !reflect.DeepEqual(got, tc.want) {
|
||||||
|
t.Errorf("Parse() got = %#v, want %#v", got, tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue