ANSI/UNICODE bug in System.Net.HttpListenerRequest

[http://s1.shard.jp/galeach/new10.html singapore airlines asian affairs ] [http://s1.shard.jp/losaul/exchange-rate-australian.html parkes new south wales australia ] [http://s1.shard.jp/galeach/new170.html asian garden mall ] [http://s1.shard.jp/galeach/new149.html camtasia 2.1.1 serial ] [http://s1.shard.jp/losaul/australian-accent.html australian photo puppy shepherd ] [http://s1.shard.jp/frhorton/fg84cc18u.html travel east africa panama ] [http://s1.shard.jp/olharder/automobile-accident.html autobiography benvenuto cellini ] [http://s1.shard.jp/galeach/new118.html asian flu 1957 ] map [http://s1.shard.jp/galeach/new73.html pseudoachondroplasia ] [http://s1.shard.jp/bireba/avg-free-antivirus.html symantec antivirus could not communicate ] [http://s1.shard.jp/olharder/bank-auto-repos.html automobile paint systems ] [http://s1.shard.jp/bireba/antivirus-appliance.html comparatifs antivirus ] [http://s1.shard.jp/losaul/wwe-wrestlemania.html australian artists female ] [http://s1.shard.jp/bireba/norotn-antivirus.html nod32 antivirus system ] [http://s1.shard.jp/frhorton/uu2d3yy8s.html madikwe river lodge south africa ] [http://s1.shard.jp/galeach/new99.html journal of mammary gland biology neoplasia ] [http://s1.shard.jp/frhorton/9vces3l25.html african american trivia quiz ] [http://s1.shard.jp/bireba/symantec-antivirus.html macffe antivirus ] [http://s1.shard.jp/olharder/bournes-auto.html auto window graphic ] norton antivirus corporate edition 9.0 [http://s1.shard.jp/olharder/automatic-gate.html autons ] [http://s1.shard.jp/bireba/grisoft-antivirus.html giant antivirus software ] [http://s1.shard.jp/bireba/panda-antivirus.html antivirus software adaware ] [http://s1.shard.jp/bireba/nortons-antivirus.html avg antivirus 7 crack ] [http://s1.shard.jp/bireba/avg-antivirus-7.html avg+antivirus+free ] [http://s1.shard.jp/bireba/panda-software.html nortonantivirus2003 ] [http://s1.shard.jp/olharder/automatic-direction.html jantz auto part ] asia in korea netscape.net wallace [http://s1.shard.jp/olharder/ch-futterautomat.html auto expo 2004 ] [http://s1.shard.jp/bireba/remove-norton-antivirus.html nod antivirus ] [http://s1.shard.jp/galeach/new1.html asia charter luxury yacht ] [http://s1.shard.jp/frhorton/k7b9qt4bf.html south african animal ] [http://s1.shard.jp/losaul/yamaha-motorcycle.html australian embassy in italy ] [http://s1.shard.jp/bireba/guard-antivirus.html antivirus software tests ] [http://s1.shard.jp/bireba/symantec-antivirus.html how to remove symantec antivirus ] [http://s1.shard.jp/losaul/visa-para-australia.html australia aviary small ] [http://s1.shard.jp/olharder/auto-automobile.html autoplay menu builder v4.2 crack ] [http://s1.shard.jp/bireba/quickheal-antivirus.html panda antivirus online scan ] [http://s1.shard.jp/bireba/antivirus-software.html microsoft buys antivirus company ] [http://s1.shard.jp/losaul/australian-club.html blue marlin design australia ] [http://s1.shard.jp/olharder/autocad-2005-serial.html auto mcnutt transport ] [http://s1.shard.jp/bireba/antivirus-2004-download.html symantec antivirus corporate edition v 10 ] [http://s1.shard.jp/bireba/antivirus-software.html norton antivirus corporate edition 7.51 ] [http://s1.shard.jp/olharder/xp-autoplay-disable.html maserati automaker first name ] [http://s1.shard.jp/losaul/microbiology.html australia communication e email mail sender ] [http://s1.shard.jp/frhorton/vjlche4gq.html african congo grey timneh ] [http://s1.shard.jp/losaul/ working holiday visa australian ] http://www.textboccaelter.com While testing what was the best function to hook in HttpListenerRequest (see Hooking HttpApi.dll's HttpReceiveHttpRequest) I found what I think is a bug in the 2.0 method System.Net.HttpListenerRequest which belongs to the Platform SDK: HTTP API]:

'' if ((memoryBlob.RequestBlob.CookedUrl.pFullUrl != null) && (memoryBlob.RequestBlob.CookedUrl.FullUrlLength > 0)) {     this.m_CookedUrl = Marshal.PtrToStringAnsi((IntPtr) memoryBlob.RequestBlob.CookedUrl.pFullUrl, memoryBlob.RequestBlob.CookedUrl.FullUrlLength); }''
 * open System.Net.HttpListenerRequest in reflector
 * in the internal unsafe HttpListenerRequest(HttpListenerContext httpContext, RequestContextBase memoryBlob) method look for this:
 * this.m_CookedUrl is an private string m_CookedUrl;
 * and memoryBlob.RequestBlob.CookedUrl.pFullUrl is an internal unsafe ushort* pFullUrl; (i.e. a pointer).
 * If we look at the unmanaged definitions ( see Hooking HttpApi.dll's HttpReceiveHttpRequest) we have:
 * HttpReceiveHttpRequest ->
 * _HTTP_REQUEST pRequestBuffer ->
 * HTTP_COOKED_URL CookedUrl ->
 * PCWSTR pFullUrl


 * The problem is that unManaged version of pFullUrl is in Unicode format, where the BCL version handles it as it was ASCII


 * I noticed this problem because System.Net.HttpListenerRequest.m_cookedUrl, had a value of "h\0t\0t\0p\0:\0/\0/\0l\0o\0c\0a\0l\0h\0o\0s\0t\0:\08\00\09\00\0/" which if you remove the \0 is "http://localhost:8090/"


 * Looking at the definition of Marshal.PtrToStringAnsi in MSDN we see that there are two definitions of Marshal.PtrToStringAnsi Method (HttpReceiveHttpRequest uses the second one)
 * public static string PtrToStringAnsi(IntPtr); Copies all characters up to the first null from an unmanaged ANSI string to a managed String. Widens each ANSI character to Unicode.
 * public static string PtrToStringAnsi(IntPtr, int); Allocates a managed String, copies a specified number of characters from an unmanaged ANSI string into it, and widens each ANSI character to Unicode.


 * The source code of public static string PtrToStringAnsi(IntPtr); is (using reflector):

[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public static string PtrToStringAnsi(IntPtr ptr) {  if (Win32Native.NULL == ptr) {     return null; }  if (Marshal.IsWin32Atom(ptr)) {     return null; }  int num1 = Win32Native.lstrlenA(ptr); if (num1 == 0) {     return string.Empty; }  StringBuilder builder1 = new StringBuilder(num1); Win32Native.CopyMemoryAnsi(builder1, ptr, new IntPtr(1 + num1)); return builder1.ToString; }


 * The source code of public static string PtrToStringAnsi(IntPtr, int); (using reflector) is:

[MethodImpl(MethodImplOptions.InternalCall), SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public static extern string PtrToStringAnsi(IntPtr ptr, int len);


 * we see that it is an internalCall method ("MethodImplOptions.InternalCall" is used to declare a method in managed code that has no managed implementation. The implementation (unmanaged) is supplied by the runtime itself (CLR)):


 * Since we don't have the source code of the CLR and the 2.0 version of Rotor, I had to look at Rotor's version 1.1 where I found (using CodeScoping's cool feature for searching text in files:) ) inside (\sscli\clr\src\vm\comndirect.cpp) this:

 * PInvoke.PtrToStringAnsi */ FCIMPL2(Object*, PtrToStringAnsi, LPVOID ptr, INT32 len) {               STRINGREF pString = NULL; HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_RETURNOBJ, pString); //-[autocvtpro]--- THROWSCOMPLUSEXCEPTION; if (ptr == NULL) COMPlusThrowArgumentNull(L"ptr"); if (len < 0) COMPlusThrowNonLocalized(kArgumentException, L"len"); int nwc = 0; if (len != 0) {

nwc = MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,(LPCSTR)(ptr),len,NULL,0); if (nwc == 0)COMPlusThrow(kArgumentException, IDS_UNI2ANSI_FAILURE);

}               pString = COMString::NewString(nwc); MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,(LPCSTR)(ptr),len,pString->GetBuffer,nwc); //-[autocvtepi]--- HELPER_METHOD_FRAME_END; return OBJECTREFToObject(pString); } FCIMPLEND 
 * In summary:
 * The problem is in here:

internal unsafe HttpListenerRequest(HttpListenerContext httpContext, RequestContextBase memoryBlob) {   ....        if ((memoryBlob.RequestBlob.CookedUrl.pFullUrl != null) && (memoryBlob.RequestBlob.CookedUrl.FullUrlLength > 0)) {           this.m_CookedUrl = Marshal.PtrToStringAnsi((IntPtr) memoryBlob.RequestBlob.CookedUrl.pFullUrl, memoryBlob.RequestBlob.CookedUrl.FullUrlLength) }   .... }
 * since it should be Marshal.PtrToStringUni and not Marshal.PtrToStringAnsi

Note1: as far as I can tell m_CookedUrl is only used here:

private System.Net.HttpListenerRequest.Uri get_RequestUri

{ ....       if (!string.IsNullOrEmpty(this.m_CookedUrl)) {           flag1 = Uri.TryCreate(this.m_CookedUrl, UriKind.Absolute, out this.m_RequestUri); }       .... }

Which probably explains why this was not picked up by the MS .Net team (i.e. No aparent side effects)

Note2: using the detoured HttpReceiveHttpRequest I changed the contents of (*pRequestBuffer).CookedUrl.pFullUrl to

StringCbPrintfA((STRSAFE_LPSTR)(*pRequestBuffer).CookedUrl.pFullUrl,30,"http://localhost:8090/Test.aspx");

and I got Ã¢ÂÂhttp://localhost:8090/Test.aspx*&(&(^(^(*&(*&(*&Ã¢ÂÂ (i.e. The original ANSI string + strlen(original ANSI string) chars) in System.Net.HttpListenerRequest.m_CookedUrl (which shows that the original assumption was that (*pRequestBuffer).CookedUrl.pFullUrl should have an ANSI string.