|
9 | 9 | "os" |
10 | 10 | "path/filepath" |
11 | 11 | "runtime" |
| 12 | + "strconv" |
| 13 | + "strings" |
12 | 14 | "testing" |
13 | 15 |
|
14 | 16 | "github.com/arduino/go-paths-helper" |
@@ -259,6 +261,74 @@ func TestSymLinkMazeHardening(t *testing.T) { |
259 | 261 | }) |
260 | 262 | } |
261 | 263 |
|
| 264 | +func TestUnixPermissions(t *testing.T) { |
| 265 | + // Disable user's umask to enable creation of files with any permission, restore it after the test |
| 266 | + userUmask := UnixUmaskZero() |
| 267 | + defer UnixUmask(userUmask) |
| 268 | + |
| 269 | + archiveFilenames := []string{ |
| 270 | + "testdata/permissions.zip", |
| 271 | + "testdata/permissions.tar", |
| 272 | + } |
| 273 | + for _, archiveFilename := range archiveFilenames { |
| 274 | + tmp, err := paths.MkTempDir("", "") |
| 275 | + require.NoError(t, err) |
| 276 | + defer tmp.RemoveAll() |
| 277 | + |
| 278 | + f, err := paths.New(archiveFilename).Open() |
| 279 | + require.NoError(t, err) |
| 280 | + err = extract.Archive(context.Background(), f, tmp.String(), nil) |
| 281 | + require.NoError(t, err) |
| 282 | + |
| 283 | + filepath.Walk(tmp.String(), func(path string, info os.FileInfo, _ error) error { |
| 284 | + filename := filepath.Base(path) |
| 285 | + // Desired permissions indicated by part of the filenames inside the zip/tar files |
| 286 | + if strings.HasPrefix(filename, "dir") { |
| 287 | + desiredPermString := strings.Split(filename, "dir")[1] |
| 288 | + desiredPerms, _ := strconv.ParseUint(desiredPermString, 8, 32) |
| 289 | + require.Equal(t, os.ModeDir|os.FileMode(OsDirPerms(desiredPerms)), info.Mode()) |
| 290 | + } else if strings.HasPrefix(filename, "file") { |
| 291 | + desiredPermString := strings.Split(filename, "file")[1] |
| 292 | + desiredPerms, _ := strconv.ParseUint(desiredPermString, 8, 32) |
| 293 | + require.Equal(t, os.FileMode(OsFilePerms(desiredPerms)), info.Mode()) |
| 294 | + } |
| 295 | + return nil |
| 296 | + }) |
| 297 | + } |
| 298 | +} |
| 299 | + |
| 300 | +func TestZipDirectoryPermissions(t *testing.T) { |
| 301 | + // Disable user's umask to enable creation of files with any permission, restore it after the test |
| 302 | + userUmask := UnixUmaskZero() |
| 303 | + defer UnixUmask(userUmask) |
| 304 | + |
| 305 | + // This arduino library has files before their containing directories in the zip, |
| 306 | + // so a good test case that these directory permissions are created correctly |
| 307 | + archive := paths.New("testdata/filesbeforedirectories.zip") |
| 308 | + download(t, "https://downloads.arduino.cc/libraries/github.com/arduino-libraries/LiquidCrystal-1.0.7.zip", archive) |
| 309 | + |
| 310 | + tmp, err := paths.MkTempDir("", "") |
| 311 | + require.NoError(t, err) |
| 312 | + defer tmp.RemoveAll() |
| 313 | + |
| 314 | + f, err := archive.Open() |
| 315 | + require.NoError(t, err) |
| 316 | + err = extract.Archive(context.Background(), f, tmp.String(), nil) |
| 317 | + require.NoError(t, err) |
| 318 | + |
| 319 | + filepath.Walk(tmp.String(), func(path string, info os.FileInfo, _ error) error { |
| 320 | + // Test files and directories (excluding the parent) match permissions from the zip file |
| 321 | + if path != tmp.String() { |
| 322 | + if info.IsDir() { |
| 323 | + require.Equal(t, os.ModeDir|os.FileMode(OsDirPerms(0755)), info.Mode()) |
| 324 | + } else { |
| 325 | + require.Equal(t, os.FileMode(OsFilePerms(0644)), info.Mode()) |
| 326 | + } |
| 327 | + } |
| 328 | + return nil |
| 329 | + }) |
| 330 | +} |
| 331 | + |
262 | 332 | // MockDisk is a disk that chroots to a directory |
263 | 333 | type MockDisk struct { |
264 | 334 | Base string |
@@ -289,3 +359,13 @@ func (m MockDisk) OpenFile(name string, flag int, perm os.FileMode) (*os.File, e |
289 | 359 | func (m MockDisk) Remove(path string) error { |
290 | 360 | return os.Remove(filepath.Join(m.Base, path)) |
291 | 361 | } |
| 362 | + |
| 363 | +func (m MockDisk) Stat(name string) (os.FileInfo, error) { |
| 364 | + name = filepath.Join(m.Base, name) |
| 365 | + return os.Stat(name) |
| 366 | +} |
| 367 | + |
| 368 | +func (m MockDisk) Chmod(name string, mode os.FileMode) error { |
| 369 | + name = filepath.Join(m.Base, name) |
| 370 | + return os.Chmod(name, mode) |
| 371 | +} |
0 commit comments