123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- // Copyright 2017 Google Inc. All rights reserved.
- //
- // Licensed 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.
- package fs
- import (
- "os"
- "reflect"
- "runtime"
- "testing"
- )
- func TestParseDirent(t *testing.T) {
- testCases := []struct {
- name string
- in []byte
- out []*dirEntryInfo
- }{
- {
- // Test that type DT_DIR is translated to os.ModeDir
- name: "dir",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x28, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- },
- out: []*dirEntryInfo{
- {".module_paths", os.ModeDir, true},
- },
- },
- {
- // Test that type DT_REG is translated to a regular file
- name: "file",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x28, 0x00,
- // unsigned char d_type;
- 0x08,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- },
- out: []*dirEntryInfo{
- {".module_paths", 0, true},
- },
- },
- {
- // Test that type DT_LNK is translated to a regular os.ModeSymlink
- name: "symlink",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x28, 0x00,
- // unsigned char d_type;
- 0x0a,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- },
- out: []*dirEntryInfo{
- {".module_paths", os.ModeSymlink, true},
- },
- },
- {
- // Test that type DT_UNKNOWN sets modeExists: false
- name: "unknown",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x28, 0x00,
- // unsigned char d_type;
- 0x00,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- },
- out: []*dirEntryInfo{
- {".module_paths", 0, false},
- },
- },
- {
- // Test a name with no padding after the null terminator
- name: "no padding",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x20, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
- },
- out: []*dirEntryInfo{
- {".module_path", os.ModeDir, true},
- },
- },
- {
- // Test two sequential entries
- name: "two entries",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x28, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x28, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x74,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- },
- out: []*dirEntryInfo{
- {".module_paths", os.ModeDir, true},
- {".module_patht", os.ModeDir, true},
- },
- },
- {
- // Test two sequential entries with no padding between them
- name: "two entries no padding",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x20, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x28, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- },
- out: []*dirEntryInfo{
- {".module_path", os.ModeDir, true},
- {".module_paths", os.ModeDir, true},
- },
- },
- {
- // Test an empty buffer. This shouldn't happen in practice because
- // readdir doesn't call parseDirent if no bytes were returned.
- name: "empty",
- in: []byte{},
- out: nil,
- },
- {
- name: "missing null terminator",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x20, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
- },
- out: []*dirEntryInfo{
- {".module_paths", os.ModeDir, true},
- },
- },
- {
- // Test two sequential entries where the first has an incorrect d_reclen.
- // Should return with no entries.
- name: "two entries first malformed",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x10, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x28, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- },
- out: nil,
- },
- {
- // Test two sequential entries where the second has an incorrect d_reclen.
- // Should return the first entry.
- name: "two entries second malformed",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x28, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x10, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- },
- out: []*dirEntryInfo{
- {".module_path", os.ModeDir, true},
- },
- },
- {
- // Test a reclen that goes past the end of the buffer.
- name: "overrun",
- in: []byte{
- // __ino64_t d_ino;
- 0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
- // __off64_t d_off;
- 0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
- // unsigned short int d_reclen;
- 0x30, 0x00,
- // unsigned char d_type;
- 0x04,
- // char d_name[];
- 0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
- },
- out: nil,
- },
- }
- if runtime.GOOS != "linux" {
- t.Skip("depends on Linux definitions of syscall.Dirent")
- }
- for _, testCase := range testCases {
- t.Run(testCase.name, func(t *testing.T) {
- entries := parseDirent(testCase.in, nil)
- if !reflect.DeepEqual(testCase.out, entries) {
- t.Fatalf("expected:\n %v\ngot:\n %v\n", testCase.out, entries)
- }
- })
- }
- }
|