ntdll: Catch page faults in NtQueryPerformanceCounter.

Sebastian Lackner sebastian at fds-team.de
Thu Jan 26 10:05:10 CST 2017


Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---

This fixes an old application which passes an invalid pointer and
does not seem to care about the return value. I have not found any
evidence that something unexpected is going on, so I suspect the
same is also happening on Windows.

I have intentionally kept the !counter check as fast path (there
is no need to call monotonic_counter in this case), but if
preferred we can also remove it.

 dlls/ntdll/tests/time.c |   23 +++++++++++++++++++++++
 dlls/ntdll/time.c       |   14 ++++++++++++--
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/tests/time.c b/dlls/ntdll/tests/time.c
index 48f4640ebb8..b684bc1980d 100644
--- a/dlls/ntdll/tests/time.c
+++ b/dlls/ntdll/tests/time.c
@@ -26,6 +26,7 @@
 
 static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ;
 static VOID (WINAPI *pRtlTimeFieldsToTime)(  PTIME_FIELDS TimeFields,  PLARGE_INTEGER Time) ;
+static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
 
 static const int MonthLengths[2][12] =
 {
@@ -94,13 +95,35 @@ static void test_pRtlTimeToTimeFields(void)
     }
 }
 
+static void test_NtQueryPerformanceCounter(void)
+{
+    LARGE_INTEGER counter, frequency;
+    NTSTATUS status;
+
+    status = pNtQueryPerformanceCounter(NULL, NULL);
+    ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
+    status = pNtQueryPerformanceCounter(NULL, &frequency);
+    ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
+    status = pNtQueryPerformanceCounter(&counter, (void *)0xdeadbee0);
+    ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
+    status = pNtQueryPerformanceCounter((void *)0xdeadbee0, &frequency);
+    ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
+
+    status = pNtQueryPerformanceCounter(&counter, NULL);
+    ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
+    status = pNtQueryPerformanceCounter(&counter, &frequency);
+    ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
+}
+
 START_TEST(time)
 {
     HMODULE mod = GetModuleHandleA("ntdll.dll");
     pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
     pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
+    pNtQueryPerformanceCounter = (void *)GetProcAddress(mod, "NtQueryPerformanceCounter");
     if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime)
         test_pRtlTimeToTimeFields();
     else
         win_skip("Required time conversion functions are not available\n");
+    test_NtQueryPerformanceCounter();
 }
diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c
index d232c4c111a..73ab39eb252 100644
--- a/dlls/ntdll/time.c
+++ b/dlls/ntdll/time.c
@@ -46,6 +46,7 @@
 #define WIN32_NO_STATUS
 #include "windef.h"
 #include "winternl.h"
+#include "wine/exception.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
 #include "ntdll_misc.h"
@@ -474,8 +475,17 @@ NTSTATUS WINAPI NtQueryPerformanceCounter( LARGE_INTEGER *counter, LARGE_INTEGER
 {
     if (!counter) return STATUS_ACCESS_VIOLATION;
 
-    counter->QuadPart = monotonic_counter();
-    if (frequency) frequency->QuadPart = TICKSPERSEC;
+    __TRY
+    {
+        counter->QuadPart = monotonic_counter();
+        if (frequency) frequency->QuadPart = TICKSPERSEC;
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        return STATUS_ACCESS_VIOLATION;
+    }
+    __ENDTRY
+
     return STATUS_SUCCESS;
 }
 
-- 
2.11.0



More information about the wine-patches mailing list