May, 2008

  • Never doubt thy debugger

    Select date ranges with LogParser


    Here’s an addendum to my previous LogParser collection of scripts: how can we filter our IIS logs folder to extract only the events happened in a certain time range?

    logparser "select * into 27.5.log from med*.log where to_timestamp(date,time) 
    between timestamp('2008/05/27 10:11:00', 'yyyy/MM/dd hh:mm:ss') and timestamp('2008/05/27 10:13:00', 'yyyy/MM/dd hh:mm:ss')" 
    -i:iisw3c -o:nat -rtp:-1

    Note I’m using the to_timestamp conversion to combine date and time fields from the IIS log and compare to the date range I’m interested in.


    Quote of the day:
    The important thing in science is not so much to obtain new facts as to discover new ways of thinking about them. - Sir William Bragg
  • Never doubt thy debugger

    Switch thread using the ThreadID


    Quick hint for today: how do you switch the thread you’re examining in Windbg? If you know the thread number you can type the command ~<thread number>s (e.g. ~21s to switch to thread 21).

    But what about if you only know the ThreadID (which is an hexadecimal value)? For example if you examine the output of the !lock command:

    0:000> !locks
    CritSec mscorwks!ThreadpoolMgr::WorkerCriticalSection+0 at 7a393800
    WaiterWoken        No
    LockCount          21
    RecursionCount     1
    OwningThread       26a0
    EntryCount         0
    ContentionCount    15
    *** Locked

    What thread is 26a0? Well… you can display all available threads (with the managed !sos.threads command or the native ~ [tilde] command) and then manually look for the ID, or use the following:

    0:000> ~~[26a0]s
    eax=000057b4 ebx=00000000 ecx=79f40a2b edx=18926823 esi=000e194c edi=000006c4
    eip=7c82ed54 esp=02d2fbf0 ebp=02d2fc2c iopl=0         nv up ei pl zr na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
    7c82ed54 c3              ret

    ~~[<threadID>]s (e.g. ~~[26a0]s), and with the sample above Windbg will switch to thread 21 smile_regular



    Quote of the day:
    Knowledge is power, if you know it about the right person. - Ethel Mumford
  • Never doubt thy debugger

    Are you using safe Http Headers?


    There are a variety of web applications out there which are relying on http headers for different purposes: automatic redirection, streaming a binary file to the client, controlling how content is cached on the client, adapting the site’s functionalities and interface to the capabilities of the browse and a lot more I’m sure you can think to.

    If you’re upgrading to ASP.NET 2.0 (or higher) an existing application which relies on http headers, you might encounter some problems, especially in the case you’re producing binary context (say a PDF file) to your clients: corrupted file, or type not supported, or inability to print the downloaded document are some of the symptoms you may get.

    First, check your code if you have something like the following:

    Response.ContentType = "application/pdf"; 
    Response.AppendHeader("Content-Disposition", "attachment; filename=document.pdf"); 
    Response.AddHeader("Content-Length", m.GetBuffer().Length.ToString()); 
    ObjPdf writer = ObjPdf.getInstance(document, m); 

    Try changing it to this:

    Response.ContentType = "application/pdf"; 
    Response.AppendHeader("Content-Disposition", "attachment; filename=document.pdf"); 
    ObjPdf writer = ObjPdf.getInstance(document, m); 
    Response.AddHeader("Content-Length", m.GetBuffer().Length.ToString()); 

    If m.GetByffer().Length is zero then you have a problem, so it’s important to open the writer object before adding the header.


    If that’s enough or you don’t want to change your code (maybe because too many pages are affected) then you can change your web.config:

                <httpWebRequest useUnsafeHeaderParsing=”true/> 

    The useUnsafeHeaderParsing config option will relax the header parsing so that headers do not have to strictly follow the standard described in the HTTP RFC. This option has been added for backwards compatibility, because the header parsing has been hanged to be very strict. Unfortunately a fair number of servers do not correctly follow the RFC, so clients using these servers will probably break due to this change. However, not using strict header parsing is a security risk, because malicious servers could send the client malformed headers which the client will then handle incorrectly. If you don't use the config option to turn off the strict parsing you probably won't get the server protocol error, but you open up the client to attack. The best solution is to try and get the server fixed.

    When this property is set to false, the following validations are performed during HTTP parsing:

    • In end-of-line code, use CRLF; using CR or LF alone is not allowed
    • Headers names should not have spaces in them
    • If multiple status lines exist, all additional status lines are treated as malformed header name/value pairs
    • The status line must have a status description, in addition to a status code
    • Header names cannot have non-ASCII chars in them. This validation is performed whether this property is set to true or false

    When a protocol violation occurs, a WebException exception is thrown with the status set to ServerProtocolViolation. If the UseUnsafeHeaderParsing property is set to true, validation errors are ignored. Setting this property to true has security implications, so it should only be done if backward compatibility with a server is required.



    Quote of the day:
    I'm not sure I want popular opinion on my side -- I've noticed those with the most opinions often have the fewest facts. - Bethania McKenstry
  • Never doubt thy debugger

    “Invalid postback or callback argument” in ASP.NET


    I saw this error twice recently, but as often happens for two completely different cases so here they are, hope it helps someone to same their time…

    Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation

    Nested forms

    The first problematic application was dynamically building page layout and manipulating the HTML stream sent to the client; in my specific case there was some manipulation carried on the client through Javascript, but I think the same may happen if for example the HTML stream is changed through an HttpHandler after the main ASP.NET processing has been completed. The page was rendered correctly within the browser, but a postback thrown the exception above and this was due to a malformed page structure, where we had nested <form> tags like in the following example:

        <form id="form1" runat="server">
                <asp:Button ID="Button1" runat="server" Text="Button" />

    There was a bug in the page, so the solution is to fix it to avoid the nested <fom> tags.

    Hidden postback control

    Here we had a DataGrid and on the ItemCreated event the customer was calling Item.Attributes.Add() to add a call to __DoPostBack() and have an automatic postback when a record was selected; needless to say, the postback attempt returned the error at the beginning of the post.

    The customer had defined a “Select” column with a button to actually select the row within the DataGrid and set the Visible property of this button to false; ASP.NET renders the button to select the record as a LinkButton. This also emits the __DoPostBack() javascript method and registers it for event validation calling ClientScript.RegisterForEventValidation(); as you can imagine, if the control is not visible (i.e. Visible=”false”) the control is not rendered and therefore is not registered for event validation. But the DataGrid uses that event anyway, which ultimately throws the error.

    The solution in this case is to manually register each row for event validation with code similar to the following:

    protected override void Render(HtmlTextWriter writer) 
        foreach (DataGridItem row in DataGrid1.Items) 
        ClientScript.RegisterForEventValidation(row.UniqueID.ToString() + ":_ctl0"); 

    The event validation must be registered within the Render() method of the page.

    Also note that there could be different degrees of added complexity to this scenario: for example if the name of the control causing the postback is built dynamically and maybe the application has been migrated from ASP.NET 1.1 to 2.0, you have to be aware that the naming convention for dynamic controls has changed. ASP.NET 1.1 uses DataGrid1$_ctl2$_ctl0 while ASP.NET 2.0 uses DataGrid1$ctl02$ctl00. It is possible to control this behavior setting xhtmlConformance=”Legacy” (see xhtmlConformance); however note that reverting back to Legacy mode causes ASP.NET 2.0 to use a column (“:”) sign in control names for event validation, instead of the dollar sign (“$”) which uses for rendering.



    Quote of the day:
    Read, every day, something no one else is reading. Think, every day, something no one else is thinking. Do, every day, something no one else would be silly enough to do. It is bad for the mind to be always part of unanimity. - Christopher Morley
Page 1 of 1 (4 items)