Skip to content

fsnotify can crash on windows if raw.FileNameLength exceeds syscall.MAX_PATH #318

@hu13

Description

@hu13

Before reporting an issue, please ensure you are using the latest release of fsnotify.
Yeah

Which operating system (GOOS) and version are you using?

Windows: go 1.12, windows 10

Please describe the issue that occurred.

panic: runtime error: slice bounds out of range

goroutine 765 [running, locked to thread]:

filesync_daemon/fsnotify.(*Watcher).readEvents(0xc000c78f40)

        /home/builder/go/src/filesync_daemon/fsnotify/windows.go:456 +0xfb1

created by filesync_daemon/fsnotify.NewWatcher

        /home/builder/go/src/filesync_daemon/fsnotify/windows.go:46 +0x21c

On windows, when we try to extract the event path name from the OS, we create a buf with length as syscall.MAX_PATH (https://github.com/fsnotify/fsnotify/blob/master/windows.go#L454).
However, it is possible to create a file name whose length exceeds this.

So, can we instead of using a fixed syscall.MAX_PATH buf, we create a buf that is the size of the path name based on the raw.FileNameLength like the following?

size := int(raw.FileNameLength / 2)
var buf []uint16
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
sh.Data = uintptr(unsafe.Pointer(&raw.FileName))
sh.Len = size
sh.Cap = size

name := syscall.UTF16ToString(buf)

Code to create a long path dir exceeding syscall.MAX_PATH:

// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows

package main

import (
	"crypto/rand"
	"encoding/hex"
	fmt "fmt"
	"os"
	"path/filepath"
)

func RandString(bytes int) string {
	buf := make([]byte, bytes)
	_, err := rand.Read(buf)
	if err != nil {
		return ""
	}
	return hex.EncodeToString(buf[:])[:len(buf)]
}

func main() {

	longPath := ""
	for i := 0; i < 10; i++ {
		longPath = filepath.Join(longPath, RandString(26))
	}

	parentDir := "C:/Users/hangk/Downloads/temp"
	fmt.Println(longPath)
	err := os.MkdirAll(filepath.Join(parentDir, longPath), 0700)
	fmt.Println(err)
}

Now if we enable recursive watch on windows here: https://github.com/fsnotify/fsnotify/blob/master/windows.go#L350 by changing flag false to true, fsnotify will crash.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions