Is there a "safe" version of wcsrchr?

My FS driver’s load notify routine (PsSetLoadImageNotifyRoutine) does a check on the first parameter (PUNICODE_STRING pusPath) with the following code:

wchar_t* pwch = wcsrchr(pusPath->Buffer, (WCHAR) “\”);

Occasionally, we are getting a PAGE_FAULT_IN_NONPAGED_AREA because wcsrchr is over running past the end of pusPath->Length or pusPath->MaximumLength because its not NULL terminated before the maximum length.

The problem is that there is no way to safely tell wcsrchr the size of the buffer.

Should I just run the chars through a for loop to ensure we don’t go over or is there a better CRT function? Thanks.

Look at FsRtlDissectName, it is much better than rolling you own for the
type of stuff you appear to be doing.


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wrote in message news:xxxxx@ntfsd…
> My FS driver’s load notify routine (PsSetLoadImageNotifyRoutine) does a
> check on the first parameter (PUNICODE_STRING pusPath) with the following
> code:
>
> wchar_t* pwch = wcsrchr(pusPath->Buffer, (WCHAR) “\”);
>
> Occasionally, we are getting a PAGE_FAULT_IN_NONPAGED_AREA because wcsrchr
> is over running past the end of pusPath->Length or pusPath->MaximumLength
> because its not NULL terminated before the maximum length.
>
> The problem is that there is no way to safely tell wcsrchr the size of the
> buffer.
>
> Should I just run the chars through a for loop to ensure we don’t go over
> or is there a better CRT function? Thanks.
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4489 (20091008)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 4489 (20091008)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

Thanks for the response Don.

I’m just trying to find the name of the executable calling it, so the last member. It seems like I could call FsRtlDissectName multiple times until RemainingName is NULL.

VOID
FsRtlDissectName(
IN UNICODE_STRING Path,
OUT PUNICODE_STRING FirstName,
OUT PUNICODE_STRING RemainingName
);

I take it since “Path” is of type UNICODE_STRING, it protects against buffer overruns?

Yes, actually there is no copying happening here, all it is doing is setting
the name results to point to the path buffer with the corrent length.
Since you are looking for the last member you could just:

PWCHAR p;

p = (PWCHAR) ( (PCHAR) path.buffer) + path.length );
while ( p > path.buffer )
{
if ( *p == ‘\’ ) break;
}

// p now has the last element


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wrote in message news:xxxxx@ntfsd…
> Thanks for the response Don.
>
> I’m just trying to find the name of the executable calling it, so the last
> member. It seems like I could call FsRtlDissectName multiple times until
> RemainingName is NULL.
>
> VOID
> FsRtlDissectName(
> IN UNICODE_STRING Path,
> OUT PUNICODE_STRING FirstName,
> OUT PUNICODE_STRING RemainingName
> );
>
> I take it since “Path” is of type UNICODE_STRING, it protects against
> buffer overruns?
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4490 (20091008)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 4490 (20091008)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

Adding one missing line (because it catches me so often):

p = (PWCHAR) ( (PCHAR) path.buffer) + path.length );
while ( p > path.buffer )
{
if ( *p == ‘\’ ) break;
p–;
}

// p now has the last element

As a side note, I’ve noticed you can get away with using / as a path
delimiter sometimes. For example, cd /temp/mydir works fine. Does Win32
convert / to \ or do the file system filters and drivers need to handle /
coming in?

Doug

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:bounce-383589-
xxxxx@lists.osr.com] On Behalf Of Don Burn
Sent: Thursday, October 08, 2009 9:48 AM
To: Windows File Systems Devs Interest List
Subject: Re:[ntfsd] Is there a “safe” version of wcsrchr?

Yes, actually there is no copying happening here, all it is doing is
setting
the name results to point to the path buffer with the corrent length.
Since you are looking for the last member you could just:

PWCHAR p;

p = (PWCHAR) ( (PCHAR) path.buffer) + path.length );
while ( p > path.buffer )
{
if ( *p == ‘\’ ) break;
}

// p now has the last element


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wrote in message news:xxxxx@ntfsd…
> > Thanks for the response Don.
> >
> > I’m just trying to find the name of the executable calling it, so the
> last
> > member. It seems like I could call FsRtlDissectName multiple times
> until
> > RemainingName is NULL.
> >
> > VOID
> > FsRtlDissectName(
> > IN UNICODE_STRING Path,
> > OUT PUNICODE_STRING FirstName,
> > OUT PUNICODE_STRING RemainingName
> > );
> >
> > I take it since “Path” is of type UNICODE_STRING, it protects against
> > buffer overruns?
> >
> >
> > Information from ESET NOD32 Antivirus, version of virus
> > signature database 4490 (20091008)

> >
> > The message was checked by ESET NOD32 Antivirus.
> >
> > http://www.eset.com
> >
> >
> >
>
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4490 (20091008)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>
>
>
> —
> NTFSD is sponsored by OSR
>
> For our schedule of debugging and file system seminars
> (including our new fs mini-filter seminar) visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

Thanks, I know I am short of sleep this morning.


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“Doug” wrote in message news:xxxxx@ntfsd…
> Adding one missing line (because it catches me so often):
>
> p = (PWCHAR) ( (PCHAR) path.buffer) + path.length );
> while ( p > path.buffer )
> {
> if ( *p == ‘\’ ) break;
> p–;
> }
>
> // p now has the last element
>
>
> As a side note, I’ve noticed you can get away with using / as a path
> delimiter sometimes. For example, cd /temp/mydir works fine. Does Win32
> convert / to \ or do the file system filters and drivers need to handle /
> coming in?
>
> Doug
>
>
>
>> -----Original Message-----
>> From: xxxxx@lists.osr.com [mailto:bounce-383589-
>> xxxxx@lists.osr.com] On Behalf Of Don Burn
>> Sent: Thursday, October 08, 2009 9:48 AM
>> To: Windows File Systems Devs Interest List
>> Subject: Re:[ntfsd] Is there a “safe” version of wcsrchr?
>>
>> Yes, actually there is no copying happening here, all it is doing is
>> setting
>> the name results to point to the path buffer with the corrent length.
>> Since you are looking for the last member you could just:
>>
>> PWCHAR p;
>>
>> p = (PWCHAR) ( (PCHAR) path.buffer) + path.length );
>> while ( p > path.buffer )
>> {
>> if ( *p == ‘\’ ) break;
>> }
>>
>> // p now has the last element
>>
>>
>> –
>> Don Burn (MVP, Windows DKD)
>> Windows Filesystem and Driver Consulting
>> Website: http://www.windrvr.com
>> Blog: http://msmvps.com/blogs/WinDrvr
>>
>>
>> wrote in message news:xxxxx@ntfsd…
>> > Thanks for the response Don.
>> >
>> > I’m just trying to find the name of the executable calling it, so the
>> last
>> > member. It seems like I could call FsRtlDissectName multiple times
>> until
>> > RemainingName is NULL.
>> >
>> > VOID
>> > FsRtlDissectName(
>> > IN UNICODE_STRING Path,
>> > OUT PUNICODE_STRING FirstName,
>> > OUT PUNICODE_STRING RemainingName
>> > );
>> >
>> > I take it since “Path” is of type UNICODE_STRING, it protects against
>> > buffer overruns?
>> >
>> >
>> > Information from ESET NOD32 Antivirus, version of virus
>> > signature database 4490 (20091008)

>> >
>> > The message was checked by ESET NOD32 Antivirus.
>> >
>> > http://www.eset.com
>> >
>> >
>> >
>>
>>
>>
>> Information from ESET NOD32 Antivirus, version of virus
>> signature database 4490 (20091008)

>>
>> The message was checked by ESET NOD32 Antivirus.
>>
>> http://www.eset.com
>>
>>
>>
>>
>>
>> —
>> NTFSD is sponsored by OSR
>>
>> For our schedule of debugging and file system seminars
>> (including our new fs mini-filter seminar) visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>
>
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4490 (20091008)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 4490 (20091008)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

While they probably eval to same value, don’t you really want

if ( *p == L’\’ ) break;

d

Sent from my phone with no t9, all spilling mistakes are not intentional.

-----Original Message-----
From: Don Burn
Sent: Thursday, October 08, 2009 7:49 AM
To: Windows File Systems Devs Interest List
Subject: Re:[ntfsd] Is there a “safe” version of wcsrchr?

Yes, actually there is no copying happening here, all it is doing is setting
the name results to point to the path buffer with the corrent length.
Since you are looking for the last member you could just:

PWCHAR p;

p = (PWCHAR) ( (PCHAR) path.buffer) + path.length );
while ( p > path.buffer )
{
if ( *p == ‘\’ ) break;
}

// p now has the last element


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wrote in message news:xxxxx@ntfsd…
> Thanks for the response Don.
>
> I’m just trying to find the name of the executable calling it, so the last
> member. It seems like I could call FsRtlDissectName multiple times until
> RemainingName is NULL.
>
> VOID
> FsRtlDissectName(
> IN UNICODE_STRING Path,
> OUT PUNICODE_STRING FirstName,
> OUT PUNICODE_STRING RemainingName
> );
>
> I take it since “Path” is of type UNICODE_STRING, it protects against
> buffer overruns?
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4490 (20091008)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 4490 (20091008)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Its not the OS or FSD that allows ‘/’ so I suspect it is some library on
top (call it Win32 or POSIX or whatever…)

I’d suggest using OBJ_NAME_PATH_SEPARATOR instead of the hard coded
backslash. That way in some perverse future where Microsoft changes
this to something else, it’ll just work right.

Tony
OSR

>I’d suggest using OBJ_NAME_PATH_SEPARATOR instead of the hard coded

backslash.

This reminds me an old joke on why this:

#define PI 3.1415926535897932384626433832795

is good.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com