Skip to content

Commit 752b6ed

Browse files
committed
user: skip empty lines
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent 15f6695 commit 752b6ed

2 files changed

Lines changed: 34 additions & 24 deletions

File tree

user/user.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,17 @@ type IDMap struct {
5656
Count int64
5757
}
5858

59-
func parseLine(line []byte, v ...any) error {
59+
func parseLine(line []byte, v ...any) (ok bool, _ error) {
60+
line = bytes.TrimSpace(line)
61+
if len(line) == 0 {
62+
return false, nil
63+
}
6064
return parseParts(bytes.Split(line, []byte(":")), v...)
6165
}
6266

63-
func parseParts(parts [][]byte, v ...any) error {
67+
func parseParts(parts [][]byte, v ...any) (ok bool, _ error) {
6468
if len(parts) == 0 {
65-
// TODO(thaJeztah); do we need an "ok" return so that we can skip these in loops?
66-
return nil
69+
return false, nil
6770
}
6871

6972
for i, p := range parts {
@@ -82,18 +85,18 @@ func parseParts(parts [][]byte, v ...any) error {
8285
if len(p) != 0 {
8386
n, ok, err := parseNumeric(string(p))
8487
if err != nil {
85-
return fmt.Errorf("parsing integer field %d: %w", i, err)
88+
return true, fmt.Errorf("parsing integer field %d: %w", i, err)
8689
}
8790
if !ok {
88-
return fmt.Errorf("parsing integer field %d: %q is not numeric", i, p)
91+
return true, fmt.Errorf("parsing integer field %d: %q is not numeric", i, p)
8992
}
9093
*e = n
9194
}
9295
case *int64:
9396
if len(p) != 0 {
9497
n, err := strconv.ParseInt(string(p), 10, 64)
9598
if err != nil {
96-
return fmt.Errorf("parsing integer field %d: %w", i, err)
99+
return true, fmt.Errorf("parsing integer field %d: %w", i, err)
97100
}
98101
*e = n
99102
}
@@ -109,7 +112,7 @@ func parseParts(parts [][]byte, v ...any) error {
109112
panic(fmt.Sprintf("parseLine only accepts {*string, *int, *int64, *[]string} as arguments! %#v is not a pointer!", e))
110113
}
111114
}
112-
return nil
115+
return true, nil
113116
}
114117

115118
func ParsePasswdFile(path string) ([]User, error) {
@@ -151,8 +154,9 @@ func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
151154
// root:x:0:0:root:/root:/bin/bash
152155
// adm:x:3:4:adm:/var/adm:/bin/false
153156
p := User{}
154-
if err := parseLine(line, &p.Name, &p.Pass, &p.Uid, &p.Gid, &p.Gecos, &p.Home, &p.Shell); err != nil {
155-
// Skip malformed lines, and don't consider them.
157+
ok, err := parseLine(line, &p.Name, &p.Pass, &p.Uid, &p.Gid, &p.Gecos, &p.Home, &p.Shell)
158+
if err != nil || !ok {
159+
// Skip malformed and empty lines, and don't consider them.
156160
continue
157161
}
158162

@@ -213,8 +217,9 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
213217
// root:x:0:root
214218
// adm:x:4:root,adm,daemon
215219
p := Group{}
216-
if err := parseLine(line, &p.Name, &p.Pass, &p.Gid, &p.List); err != nil {
217-
// Skip malformed lines, and don't consider them.
220+
ok, err := parseLine(line, &p.Name, &p.Pass, &p.Gid, &p.List)
221+
if err != nil || !ok {
222+
// Skip malformed and empty lines, and don't consider them.
218223
continue
219224
}
220225

@@ -530,8 +535,9 @@ func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
530535

531536
// see: man 5 subuid
532537
p := SubID{}
533-
if err := parseLine(line, &p.Name, &p.SubID, &p.Count); err != nil {
534-
// Skip malformed lines, and don't consider them.
538+
ok, err := parseLine(line, &p.Name, &p.SubID, &p.Count)
539+
if err != nil || !ok {
540+
// Skip malformed and empty lines, and don't consider them.
535541
continue
536542
}
537543

@@ -581,8 +587,9 @@ func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
581587

582588
// see: man 7 user_namespaces
583589
p := IDMap{}
584-
if err := parseParts(bytes.Fields(line), &p.ID, &p.ParentID, &p.Count); err != nil {
585-
// Skip malformed lines, and don't consider them.
590+
ok, err := parseParts(bytes.Fields(line), &p.ID, &p.ParentID, &p.Count)
591+
if err != nil || !ok {
592+
// Skip malformed and empty lines, and don't consider them.
586593
continue
587594
}
588595

user/user_test.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,63 +21,66 @@ func TestParseLine(t *testing.T) {
2121
d int
2222
)
2323

24-
err := parseLine([]byte(""), &a, &b)
24+
_, err := parseLine([]byte(""), &a, &b)
2525
if err != nil {
2626
t.Fatal(err)
2727
}
2828
if a != "" || b != "" {
2929
t.Fatalf("a and b should be empty ('%v', '%v')", a, b)
3030
}
3131

32-
err = parseLine([]byte("a"), &a, &b)
32+
_, err = parseLine([]byte("a"), &a, &b)
3333
if err != nil {
3434
t.Fatal(err)
3535
}
3636
if a != "a" || b != "" {
3737
t.Fatalf("a should be 'a' and b should be empty ('%v', '%v')", a, b)
3838
}
3939

40-
err = parseLine([]byte("bad boys:corny cows"), &a, &b)
40+
_, err = parseLine([]byte("bad boys:corny cows"), &a, &b)
4141
if err != nil {
4242
t.Fatal(err)
4343
}
4444
if a != "bad boys" || b != "corny cows" {
4545
t.Fatalf("a should be 'bad boys' and b should be 'corny cows' ('%v', '%v')", a, b)
4646
}
4747

48-
err = parseLine([]byte(""), &c)
48+
ok, err := parseLine([]byte(""), &c)
4949
if err != nil {
5050
t.Fatal(err)
5151
}
52+
if ok {
53+
t.Fatalf("ok should be false for empty lines")
54+
}
5255
if len(c) != 0 {
5356
t.Fatalf("c should be empty (%#v)", c)
5457
}
5558

56-
err = parseLine([]byte("d,e,f:g:h:i,j,k"), &c, &a, &b, &c)
59+
_, err = parseLine([]byte("d,e,f:g:h:i,j,k"), &c, &a, &b, &c)
5760
if err != nil {
5861
t.Fatal(err)
5962
}
6063
if a != "g" || b != "h" || len(c) != 3 || c[0] != "i" || c[1] != "j" || c[2] != "k" {
6164
t.Fatalf("a should be 'g', b should be 'h', and c should be ['i','j','k'] ('%v', '%v', '%#v')", a, b, c)
6265
}
6366

64-
err = parseLine([]byte("::::::::::"), &a, &b, &c)
67+
_, err = parseLine([]byte("::::::::::"), &a, &b, &c)
6568
if err != nil {
6669
t.Fatal(err)
6770
}
6871
if a != "" || b != "" || len(c) != 0 {
6972
t.Fatalf("a, b, and c should all be empty ('%v', '%v', '%#v')", a, b, c)
7073
}
7174

72-
err = parseLine([]byte("not a number"), &d)
75+
_, err = parseLine([]byte("not a number"), &d)
7376
if err == nil {
7477
t.Fatal("expected an error")
7578
}
7679
if d != 0 {
7780
t.Fatalf("d should be 0 (%v)", d)
7881
}
7982

80-
err = parseLine([]byte("b:12:c"), &a, &d, &b)
83+
_, err = parseLine([]byte("b:12:c"), &a, &d, &b)
8184
if err != nil {
8285
t.Fatal(err)
8386
}

0 commit comments

Comments
 (0)