[PATCH][Win] Fix assertion failure when passing 'nul' in input to cc1.

Andrea Di Biagio andrea.dibiagio at gmail.com
Tue Apr 29 04:21:19 PDT 2014


Hi all,

On Windows, a device is a file of type 'FILE_TYPE_CHAR'.
In the case of 'nul', function 'getStatus' in Path.inc returns an
instance of 'file_status' with fields 'nFileSizeHigh' and
'nFileSizeLow' left uninitialized.

Later on, this might cause the triggering of an assertion failure in
MemoryBuffer.cpp:
Assertion Failed: NextLocalOffset + FileSize + 1 > NextLocalOffset &&
NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset && "Ran out of
source locations!"

I spotted this problem when running the following command from the command line:
  `clang -cc1 -x c nul -dM -E`

This patch fixes the problem modifying the constructor of
'file_status' in llvm/Support/FileSystem.h.

I have split the patch in two parts:
* An LLVM patch fixes the problem setting by default to zero all the
fields of file_status (excluding Type and Perms) in the constructor of
file_size in FileSystem.h.

* A Clang patch that adds a test to verify that the assertion no longer happens.
The test requires to be run on windows. To make that test work fine, I
modified clang/test/lit.py to add feature `system-windows' if
platform.system() is 'Windows'.

Please let me know if ok to submit.

Thanks,
Andrea Di Biagio
SN Systems - Sony Computer Entertainment Group.
-------------- next part --------------
Index: test/Frontend/windows-nul.c
===================================================================
--- test/Frontend/windows-nul.c	(revision 0)
+++ test/Frontend/windows-nul.c	(working copy)
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -dM -E nul -o /dev/null
+
+// REQUIRES: system-windows
+
+// Verify that cc1 doesn't crash with an assertion failure
+// in MemoryBuffer.cpp due to an invalid file size reported
+// when the Windows 'nul' device is passed in input.
+
Index: test/lit.cfg
===================================================================
--- test/lit.cfg	(revision 207520)
+++ test/lit.cfg	(working copy)
@@ -344,6 +344,9 @@
 # This is used by debuginfo-tests/*block*.m and debuginfo-tests/foreach.m.
 if platform.system() in ['Darwin']:
     config.available_features.add('system-darwin')
+elif platform.system() in ['Windows']:
+    # For tests that require Windows to run.
+    config.available_features.add('system-windows')
 
 # ANSI escape sequences in non-dumb terminal
 if platform.system() not in ['Windows']:
-------------- next part --------------
Index: include/llvm/Support/FileSystem.h
===================================================================
--- include/llvm/Support/FileSystem.h	(revision 207520)
+++ include/llvm/Support/FileSystem.h	(working copy)
@@ -166,14 +166,22 @@
   perms Perms;
 public:
   file_status() : Type(file_type::status_error) {}
-  file_status(file_type Type) : Type(Type) {}
 
   #if defined(LLVM_ON_UNIX)
+    file_status(file_type Type) : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0),
+        fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type),
+        Perms(perms_not_known) {}
+
     file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime,
                 uid_t UID, gid_t GID, off_t Size)
         : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID),
           fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {}
   #elif defined(LLVM_ON_WIN32)
+    file_status(file_type Type) : LastWriteTimeHigh(0), LastWriteTimeLow(0),
+        VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0),
+        FileIndexHigh(0), FileIndexLow(0), Type(Type),
+        Perms(perms_not_known) {}
+
     file_status(file_type Type, uint32_t LastWriteTimeHigh,
                 uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber,
                 uint32_t FileSizeHigh, uint32_t FileSizeLow,
@@ -183,6 +191,8 @@
           VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh),
           FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh),
           FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {}
+  #else
+    file_status(file_type Type) : Type(Type) {}
   #endif
 
   // getters


More information about the llvm-commits mailing list