c - RtlCopyMemory PUNICODE_STRING 到 WCHAR 段错误

标签 c windows kernel

我实际上是在我的内核驱动程序中将 PUNICODE_STRING 转换为恒定大小的 WCHAR[],试图避免溢出。我的方法在 99% 的情况下都有效,但有时我会从第一个 RtlCopyMemory 得到段错误,调试器最有用的输出类似于:

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced.  This cannot be protected by try-except,
it must be protected by a Probe.  Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: ffffc0016c0dd000, memory referenced.
Arg2: 0000000000000000, value 0 = read operation, 1 = write operation.
Arg3: fffff800adea85bd, If non-zero, the instruction address which referenced the bad memory
    address.
Arg4: 0000000000000000, (reserved)

我的方法有什么问题(参见下面的示例)?

typedef struct _MYRESULT {
 WCHAR Result[512];
} MYRESULT;

void myFunction(
_Inout_ MYRESULT *result,
_In_ PUNICODE_STRING s
)
{
 if (s->Length < 511) {
  // It is usually this RtlCopyMemory that crashes the kernel
  RtlCopyMemory(result->Result, s->Buffer, sizeof(WCHAR)*s->Length);
  // NULL terminate
  result->Result[(sizeof)WCHAR)*s->Length)] = 0;
 } else {
  RtlCopyMemory(result->Result, s->Buffer, sizeof(WCHAR)*512);
  // NULL terminate
  result->Result[511] = 0;
 }
}

最佳答案

代码复制了太多数据。

来自 MSDN on UNICODE_STRING (我强调):

Length

Specifies the length, in bytes, of the string pointed to by the Buffer member, not including the terminating NULL character, if any.

从对 RtlCopyMemory() 的调用中删除 sizeof(WCHAR)

void myFunction(
_Inout_ MYRESULT *result,
_In_ PUNICODE_STRING s
)

{
  if (s->Length < (511 * sizeof * result)) {
     // It is usually this RtlCopyMemory that crashes the kernel
     RtlCopyMemory(result->Result, s->Buffer, s->Length);
     // NULL terminate
     result->Result[(sizeof)WCHAR)*s->Length)] = 0;
   } else {
     RtlCopyMemory(result->Result, s->Buffer, 512);
      // NULL terminate
     result->Result[511 * sizeof * result] = 0;
   }
}

或不太容易出错(也遵循 DRY principle ):

#define RESULT_MAXIMUMLENGTH (511) /* This needs to stay smaller 
                                      then USHORT_MAX / sizeof * MYRESULT.Result. */

typedef struct _MYRESULT {
  WCHAR Result[RESULT_MAXIMUMLENGTH + 1];
} MYRESULT;

void myFunction(
_Inout_ MYRESULT *result,
_In_ PUNICODE_STRING s
)
{
  USHORT len = (s->Length < (RESULT_MAXIMUMLENGTH * sizeof * result)) 
    ? s->Length 
    : RESULT_MAXIMUMLENGTH * sizeof * result;

  RtlCopyMemory(result->Result, s->Buffer, len);
  result->Result[len] = 0;
}

经验教训:RTFM有帮助。

关于c - RtlCopyMemory PUNICODE_STRING 到 WCHAR 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29329908/

相关文章:

java - 从 Java 在 Windows 上更新文件的时间戳

windows - 如何在 Windows 7 32 位上安装 MongoDB?

python - 跨大学网络保留 Google Drive session 数据

c++ - Windows 上的堆栈 - 它在哪里?

linux - 内核模块执行中的不同特权

linux - Linux内核模块的缺点?

c - 它会比这更快吗?

c++ - L-Value,指针运算

c - 填充位图像素数组

c - FFT 2D 数组的实现