System Crash with 0x00000050 bugckeck while accessing data using virtual address

Hi,

I am working on USB device driver & have a requirement to create a mapped buffer with user allocated size. I am using IoAllocateMdl for getting main pMainMdl with required size. Than i am creating sub buffer, in case data is grater than 4Kb into chunks of each 4KB. I am getting pSubMdl for each chunk and than mapping pSubMdl to main buffer i.e pMainMdl using IoBuildPartialMdl.

Now, when i will get completion routine for each block, i want to create a thread & in that thread i want to do division to data received. workevent(thread) created & working fine.

using (PWCHAR)MmGetMdlVirtualAddress(pSubMdl); to get starting virtual address of a buffer whose completion routine occured, getting virtual address correct. But system crashes with error 0x00000050 & read failed flag 0x0000000 (paged memory fault). Actually, I have used MmBuildMdlForNonPagedPool(pMainMdl); after creating main buffer.

division i am doing as below:

PWCHAR currentmdl = (PWCHAR)MmGetMdlVirtualAddress(pSubMdl);

for (UINT length = 0; length < pIndex; length++)
{
*currentmdl/= 2;
((WCHAR)currentmdl)++;
}

if comment part *currentmdl/= 2; than no crash occurs.

> I am working on USB device driver

What about learning the basics of C language before even thinking about such an “endeavour”?

Don’t forget that arrays and pointers are equivalent in C. Therefore, after having incremented a pointer N times, the numeric value (i.e. the one casted to int type) that you get can be described with the following equation

(int) resulting_address = (int) original address + N * sizeof(pointee);

Once WCHAR happens to be two bytes long, the final result that you get is

(int)final_address=(int)original_buffer + 2*index;

In other words, you simply exceed the array bounds after index/2 iterations of a loop. As long as you don’t try to dereference a pointer everything works fine, but when you do you crash for the (hopefully) obvious reasons…

Anton Bassov

xxxxx@einfochips.com wrote:

using (PWCHAR)MmGetMdlVirtualAddress(pSubMdl); to get starting virtual address of a buffer whose completion routine occured, getting virtual address correct. But system crashes with error 0x00000050 & read failed flag 0x0000000 (paged memory fault). Actually, I have used MmBuildMdlForNonPagedPool(pMainMdl); after creating main buffer.

I am curious to know what led you to use PWCHAR here.  As Anton pointed
out, that is a big part of your problem.  It’s not the natural thing to
do, and you wouldn’t have found it in any sample, so to help future
developers I’d like to understand how you decided to do that.

division i am doing as below:

PWCHAR currentmdl = (PWCHAR)MmGetMdlVirtualAddress(pSubMdl);

for (UINT length = 0; length < pIndex; length++)
{
*currentmdl/= 2;
((WCHAR)currentmdl)++;
}

if comment part *currentmdl/= 2; than no crash occurs.

What are you actually trying to accomplish here?  This code as you have
typed it won’t actually compile; you are casting a pointer to a WCHAR
rvalue, and you can’t increment a WCHAR rvalue.  Is the idea here that
your buffer is a series of 16-bit values, and you want to divide them
all by two?  Is pIndex the length in bytes, or the length in shorts? 
Something as simple as this would work:

    PUSHORT pus = (PUSHORT)MmGetMdlVirtualAddress(pSubMdl);
    for( int i = 0; i < number_of_shorts; i++ )
        pus[i] /= 2;


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> This code as you have typed it won’t actually compile; you are casting a pointer to a

WCHAR rvalue, and you can’t increment a WCHAR rvalue.

Actually, it does compile with GCC, albeit with a “cast from pointer to integer of different size” warning.
In any case, the result that you get is equivalent to the one you would get without this stupid cast
(I tried it a minute ago just for the sake of the experiment - it seems to be “working fine”)

Anton Bassov

On Aug 17, 2018, at 4:22 PM, xxxxx@hotmail.com wrote:
>
> Actually, it does compile with GCC, albeit with a “cast from pointer to integer of different size” warning.
> In any case, the result that you get is equivalent to the one you would get without this stupid cast
> (I tried it a minute ago just for the sake of the experiment - it seems to be “working fine”)

I’m wondering what it is you actually tried, because your results certainly don’t match mine. I used this simple program, modulo the includes:

int main() {
int i = 345;
int * pi = &i;
((unsigned short)pi)++;
}

Compiling that gets “cast from pointer to smaller type”, but it is an error, not a warning:

[xxxxx@Tims-MacBook-Air:~/src]$ gcc -S x.cpp
x.cpp:9:6: error: cast from pointer to smaller type ‘unsigned short’ loses information
((unsigned short)pi)++;
^~
1 error generated.
[xxxxx@Tims-MacBook-Air:~/src]$

And if I change it to unsigned long, which is the same size, I get an error that assignments to casts are not supported, which is exactly what I would expect.

[xxxxx@Tims-MacBook-Air:~/src]$ gcc -S x.cpp
x.cpp:9:6: error: assignment to cast is illegal, lvalue casts are not supported
((unsigned long)pi)++;
~^
~~~
1 error generated.
[xxxxx@Tims-MacBook-Air:~/src]$

Think about it. How would that expression work? The ++ operator has to modify the cell it is incrementing. If you have a WCHAR, what is there to modify? There’s no address. It’s like trying to write “i = 3++;”. It CANNOT compile. It’s meaningless.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> I’m wondering what it is you actually tried,

Oooops - I have to take my words back, because there is a “bug” in my code.Look what I did

int main()
{

unsigned short var;
unsigned short *ptr=&var;

for(int x=0;x<5;x++)

((unsigned short)ptr++);

return 1;

}

In other words, I just misplaced the closing parenthesis. However, if I do it the way the OP does,
( i.e “((unsigned short)ptr)++;” ), I get, indeed, the following error:

xxxxx@debian:~/Projects/test$ make
gcc -O3 -std=c99 -c -o test.o test.c
test.c: In function ?main?:
test.c:4:30: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
test.c:4:49: error: lvalue required as increment operand
make: *** [test.o] Error 1

My apologies…

Anton Bassov