• The Old New Thing

    It rather involved being on the other side of this airtight hatchway: Denial of service by high CPU usage

    • 40 Comments

    We received the following security vulnerability report:

    Windows is vulnerable to a denial of service attack that consumes 100% CPU.

    1. Use the following procedure to create a file that is enchanted by magic pixie dust: [...]
    2. Rename the file to TEST.EXE.
    3. Execute as many copies of the program as you have CPU cores.

    Observe that CPU usage climbs to 100% and never goes down. This a clear demonstration that Windows is vulnerable to a denial of service attack from magic pixie dust.

    The magic pixie dust is a red herring. This vulnerability report is basically saying "If you are allowed to run arbitrary programs, then it is possible to run a program that consumes all the available CPU."

    Well, duh.

    This is another case of if I can run an arbitrary program, then I can do arbitrary things, also known as MS07-052: Code execution results in code execution. (Or in the lingo of Internet memes, "High CPU is high.")

    Now, of course, if the magic pixie dust somehow allows a user to do things like access resources they do not have access to, or to circumvent resource usage quotas, then there would be a serious problem here, and if if the high CPU usage could be triggered remotely, then there is a potential for a denial-of-service attack. But there was nothing of the sort. Here's a much less complicated version of magic pixie dust:

    int __cdecl main(int, char **) { for (;;) { } /*NOTREACHED*/ }
    
  • The Old New Thing

    How to take down the entire Internet with this one weird trick, according to Crisis

    • 28 Comments

    According to the television documentary Crisis which aired on NBC last Sunday, a cyberattack took over the entire Internet.

    Timecode 13:00: "Anything connected to the Internet. Banking systems, power grid, air traffic control, emergency services. The virus has spread into them all."

    And the show includes an amazing journalistic scoop: A screen shot of the attack being launched! Timecode 11:40:

    文件上传
    Threads Progress Remaining Speed
    0:000> u eip-30 eip+20 notepad+0x5cfc: 01005cfc 0001 add [ecx],al 01005cfe 3bc7 cmp eax,edi 01005d00 7407 jz notepad+0x5d09 (01005d09) 01005d02 50 push eax 01005d03 ff15dc100001 call dword ptr [notepad+0x10dc (010010dc)] 01005d09 8b45fc mov eax,[ebp-0x4] 01005d0c 57 push edi 01005d0d 57 push edi 01005d0e 68c50000 push 0xc5

    That's right, my friends. This elite virus that shut down the Internet was an upload of Notepad!

  • The Old New Thing

    Cargo-cult registry settings and the people who swear by them

    • 14 Comments

    Two customers (so far) wanted to know how to increase the duration of taskbar balloon notifications on Windows Vista. (By the way, I gave the answer some time ago.)

    They claimed that on Windows XP, they were using the registry key HKEY_CURRENT_USER\Software\Microsoft\Windows\Current­Version\Explorer\Tray­Notify, setting the value Balloon­Tip to a REG_DWORD specifying the number of seconds the balloon should appear. They wanted to know if this still worked in Vista.

    Heck, it didn't work even in Windows XP!

    That undocumented registry key actually controls whether the Windows XP taskbar should show the "To see the hidden icons, click this button" tip. It has nothing to do with how long the balloon stays on the screen.

    A quick Web search suggests that that particular setting has reached cult status, with everybody saying that the setting controls balloon duration, and nobody actually testing it. It's just a matter of faith.

    Even the sometimes-suggested trick of putting the registry key name in MSDN so searches can find it and direct users to the correct method wouldn't have helped, because this was the wrong registry key to begin with.

    (Remember, the answer is in the linked article.)

  • The Old New Thing

    Only senior executives can send email to the All Employees distribution list, but mistakes still happen

    • 26 Comments

    Some time ago, a senior executive sent email to the All Employees distribution list at Microsoft announcing that a particular product was now available for dogfood. The message included a brief introduction to the product and instructions on how to install it.

    A few hours later, a second message appeared in reply to the announcement. The second message came from a different senior executive, and it went

    I got your note and tried it out. Looks good so far.

    Oopsie. The second senior executive intended to reply just to the first senior executive, but hit the Reply All button by mistake. This would normally have been caught by the You do not have permission to send mail to All Employees rule, but since the mistake was made by a senior executive, that rule did not apply, and the message went out to the entire company.

    People got a good chuckle out of this. At least he didn't say anything embarrassing.

    Bonus chatter: I'd have thought that these extra-large distribution lists would be marked Nobody can send to this distribution list, and then when somebody needed to send a message to the entire company, the email admins would create a one-day-only rule which allowed a specific individual to send one message.

  • The Old New Thing

    Find the index of the smallest element in a JavaScript array

    • 49 Comments

    Today's Little Program isn't even a program. It's just a function.

    The problem statement is as follows: Given a nonempty JavaScript array of numbers, find the index of the smallest value. (If the smallest value appears more than once, then any such index is acceptable.)

    One solution is simply to do the operation manually, simulating how you would perform the operation with paper and pencil: You start by saying that the first element is the winner, and then you go through the rest of the elements. If the next element is smaller than the one you have, you declare that element the new provisional winner.

    function indexOfSmallest(a) {
     var lowest = 0;
     for (var i = 1; i < a.length; i++) {
      if (a[i] < a[lowest]) lowest = i;
     }
     return lowest;
    }
    

    Another solution is to use the reduce intrinsic to run the loop, so you merely have to provide the business logic of the initial guess and the if statement.

    function indexOfSmallest(a) {
     return a.reduce(function(lowest, next, index) {
                       return next < a[lowest] : index ? lowest; },
                     0);
    }
    

    A third solution is to use JavaScript intrinsics to find the smallest element and then convert the element to its index.

    function indexOfSmallest(a) {
     return a.indexOf(Math.min.apply(Math, a));
    }
    

    Which one is fastest?

    Okay, well, first, before you decide which one is fastest, you need to make sure they are all correct. One thing you discover is that the min/indexOf technique fails once the array gets really, really large, or at least it does in Internet Explorer and Firefox. (In my case, Internet Explorer and Firefox gave up at around 250,000 and 500,000 elements, respectively.) That's because you start hitting engine limits on the number of parameters you can pass to a single function. Invoking apply on an array of 250,000 elements is the equivalent of calling min with 250,000 function parameters.

    So we'll limit ourselves to arrays of length at most 250,000.

    Before I share the results, I want you to guess which algorithm you think will be the fastest and which will be the slowest.

    Still waiting.

    I expected the manual version to come in last place, because, after all, it's doing everything manually. I expected the reduce version to be slightly faster, because it offloads some of the work into an intrinsic (though the function call overhead may have negated any of that improvement). I expected the min/indexOf version to be fastest because nearly all the work is being done in intrinsics, and the cost of making two passes over the data would be made up by the improved performance of the intrinsics.

    Here are the timings of the three versions with arrays of different size, running on random data. I've normalized run times so that the results are independent of CPU speed.

    Relative running time per array element
    Elements manual reduce min/indexOf
    Internet Explorer 9
    100,000 1.000 2.155 2.739
    200,000 1.014 2.324 3.099
    250,000 1.023 2.200 2.330
    Internet Explorer 10
    100,000 1.000 4.057 4.302
    200,000 1.028 4.057 4.642
    250,000 1.019 4.091 4.068

    Are you surprised? I sure was!

    Not only did I have it completely backwards, but the margin of victory for the manual version was way beyond what I imagined.

    (This shows that the only way to know your program's performance characteristics for sure is to sit down and measure it.)

    What I think is going on is that the JavaScript optimizer can do a really good job of optimizing the manual code since it is very simple. There are no function calls, the loop body is just one line, it's all right out there in the open. The versions that use intrinsics end up hiding some of the information from the optimizer. (After all, the optimizer cannot predict ahead of time whether somebody has overridden the default implementation of Array.prototype.reduce or Math.prototype.min, so it cannot blindly inline the calls.) The result is that the manual version can run over twice as fast on IE9 and over four times as fast on IE10.

    I got it wrong because I thought of JavaScript too much like an interpreted language. In a purely interpreted language, the overhead of the interpreter is roughly proportional to the number of things you ask it to do, as opposed to how hard it was to do any of those things. It's like a fixed service fee imposed on every transaction, regardless of whether the transaction was for $100 or 50 cents. You therefore try to make one big purchase (call a complex intrinsic) instead of a lot of small ones (read an array element, compare two values, increment a variable, copy one variable to another).

    Bonus chatter: I ran the test on Firefox, too, because I happened to have it handy.

    Relative running time per array element
    Elements manual reduce min/indexOf
    Firefox 16
    100,000 1.000 21.598 3.958
    200,000 0.848 21.701 2.515
    250,000 0.839 21.788 2.090

    The same data collected on Firefox 16 (which sounds ridiculously old because Firefox will be on version 523 by the time this article reaches the head of the queue) shows a different profile, although the winner is the same. The manual loop and the min/indexOf get more efficient as the array size increases. This suggests that there is fixed overhead that becomes gradually less significant as you increase the size of the data set.

    One thing that jumps out is that the reduce method way underperforms the others. My guess is that setting up the function call (in order to transition between the intrinsic and the script) is very expensive, and that implementors of the JavaScript engines haven't spent any time optimizing this case because reduce is not used much in real-world code.

    Update: I exaggerated my naïveté to make for a better narrative. As I point out in the preface to my book, my stories may not be completely true, but they are true enough. Of course I know that JavaScript is jitted nowadays, and that changes the calculus. (Also, the hidden array copy.)

  • The Old New Thing

    Why is the debugger telling me I crashed because my DLL was unloaded, when I see it loaded right here happily executing code?

    • 8 Comments

    A customer was puzzled by what appeared to be contradictory information coming from the debugger.

    We have Windows Error Reporting failures that tell us that we are executing code in our DLL which has been unloaded. Here's a sample stack:

    Child-SP          RetAddr           Call Site
    00000037`7995e8b0 00007ffb`fe64b08e ntdll!RtlDispatchException+0x197
    00000037`7995ef80 000007f6`e5d5390c ntdll!KiUserExceptionDispatch+0x2e
    00000037`7995f5b8 00007ffb`fc977640 <Unloaded_contoso.dll>+0x3390c
    00000037`7995f5c0 00007ffb`fc978296 RPCRT4!NDRSRundownContextHandle+0x18
    00000037`7995f610 00007ffb`fc9780ed RPCRT4!DestroyContextHandlesForGuard+0xea
    00000037`7995f650 00007ffb`fc9b5ff4 RPCRT4!ASSOCIATION_HANDLE::~ASSOCIATION_HANDLE+0x39
    00000037`7995f680 00007ffb`fc9b5f7c RPCRT4!LRPC_SASSOCIATION::`scalar deleting destructor'+0x14
    00000037`7995f6b0 00007ffb`fc978b25 RPCRT4!LRPC_SCALL_BROKEN_FLOW::FreeObject+0x14
    00000037`7995f6e0 00007ffb`fc982e44 RPCRT4!LRPC_SASSOCIATION::MessageReceivedWithClosePending+0x6d
    00000037`7995f730 00007ffb`fc9825be RPCRT4!LRPC_ADDRESS::ProcessIO+0x794
    00000037`7995f870 00007ffb`fe5ead64 RPCRT4!LrpcIoComplete+0xae
    00000037`7995f910 00007ffb`fe5e928a ntdll!TppAlpcpExecuteCallback+0x204
    00000037`7995f980 00007ffb`fc350ce5 ntdll!TppWorkerThread+0x70a
    00000037`7995fd00 00007ffb`fe60f009 KERNEL32!BaseThreadInitThunk+0xd
    00000037`7995fd30 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
    

    But if we ask the debugger what modules are loaded, our DLL is right there, loaded as happy as can be:

    0:000> lm
    start             end                 module name
    ...
    000007f6`e6000000 000007f6`e6050000   contoso    (deferred)
    ...
    

    In fact, we can view other threads in the process, and they are happily running code in our DLL. What's going on here?

    All the information you need to solve this problem is given right there in the problem report. You just have to put the pieces together.

    Let's take a closer look at that <Unloaded_contoso.dll>+0x3390c entry. The address that the symbol refers to is the return address from the previous frame: 000007f6`e5d5390c. Subtract 0x3390c from that, and you get 000007f6`e5d20000, which is the base address of the unloaded module.

    On the other hand, the lm command says that the currently-loaded copy of contoso.dll is loaded at 000007f6`e6000000. This is a different address.

    What happened here is that contoso.dll was loaded into memory at 000007f6`e5d20000, and then it ran for a while. The DLL was then unloaded from memory, and later loaded back into memory. When it returned, it was loaded at a different address 000007f6`e6000000. For some reason (improper cleanup when unloading the first copy, most likely), there was still a function pointer pointing into the old unloaded copy, and when NDRS­Rundown­Context­Handle tries to call into that function pointer, it calls into an unloaded DLL, and you crash.

    When faced with something that seems impossible, you need to look more closely for clues that suggest how your implicit assumptions may be incorrect. In this case, the assumption was that there was only one copy of contoso.dll.

  • The Old New Thing

    Eventually, we may find out where notes eight through twelve came from

    • 16 Comments

    CBC Radio's Tom Allen investigates the origin of the opening four notes of the classic Star Trek theme. He traces it to the opening of Mahler's First Symphony, then further back to Brahms's Second Symphony and Beethoven's Fourth Symphony.

    In college, one of my classmates (the same one that is now the conductor of an orchestra) identified the source of the trumpet fanfare in the Star Trek theme, also known as notes five through seven: Mahler's Seventh Symphony. Skip to timecode 11:05.

    Eventually, we may find out where notes eight through twelve came from. If the trend keeps up, we may discover that it came from yet another Mahler symphony.

  • The Old New Thing

    Why does my radio button group selection get reset each time my window regains activation?

    • 10 Comments
    A customer reported (all incomplete information and red herrings preserved):

    We have an issue related to two radio buttons in a window. The code programmatically checks the second button by sending the BM_SET­CHECK message. We observe that if the user clicks somewhere else on the screen (so that our application loses focus), and then clicks on the taskbar icon to return to our application, the first radio button spontaneously gets selected.

    We watched all the messages in Spy++, and it appears that the radio button is receiving a WM_SET­FOCUS followed by a WM_SET­CHECK.

    Is this by design? If not, what should I be looking for in my code that is causing this erroneous selection change to occur?

    The incomplete information is that the customer didn't say how they created those radio buttons.

    The red herring is that the customer said that they had a problem with their window. This suggested that they were doing a custom window implementation (because if they were using the standard dialog implementation, they would have said dialog).

    But from the symptoms, it's clear that what's most likely happening is that the radio button is created as a BS_AUTO­RADIO­BUTTON. And automatic radio buttons select themselves automatically (hence the name) when they receive focus.

    That explains the message sequence of WM_SET­FOCUS followed by a WM_SET­CHECK: The automatic radio button receives focus, and in response it checks itself.

    Therefore, the next level of investigation is why the first radio button is getting focus when the window is activated.

    If the application window is a custom window, then the place to look is their window's activation and focus code, to see why focus is going to the first radio button instead of the second one. Perhaps it is putting focus on the first radio button temporarily, and then later realizes, "Oh wait, I really meant to put it on the second radio button." The fix would be to get rid of the temporary focus change and go straight to the second radio button.

    If the application window is a standard dialog, then we saw last time that the dialog manager restores focus to the window that had focus last, and that you could mimic the same behavior in your own code.

    It turns out that the customer was indeed using a standard dialog, in which case the problem is that they put the dialog into an inconsistent state: They checked the second radio button but left focus on the first radio button. This is a configuration that exists nowhere in nature, and therefore when the dialog manager tries to recreate it (given its lack of specialized knowledge about specific controls), it can't.

    The fix is to put focus on the second radio button as well as setting the check box. In fact, you can accomplish both by setting the focus to the second radio button (noting that there is a special process for setting focus in a dialog box) since you already are using automatic radio buttons.

    Here's a program that demonstrates the problem:

    // scratch.rc
    
    1 DIALOGEX 32, 32, 160, 38
    STYLE DS_MODALFRAME | DS_SHELLFONT | WS_POPUP | WS_VISIBLE |
          WS_CAPTION | WS_SYSMENU
    CAPTION "Test"
    FONT 9, "MS Shell Dlg"
    BEGIN
    CONTROL "First", 100, "Button",
            WS_GROUP | WS_TABSTOP | BS_AUTORADIOBUTTON, 4,  4, 152, 13
    CONTROL "Second", 101, "Button",BS_AUTORADIOBUTTON, 4, 20, 152, 13
    END
    
    // scratch.cpp
    
    #include <windows.h>
    #include <windowsx.h>
    
    INT_PTR CALLBACK DlgProc(
        HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
     switch (uMsg) {
     case WM_INITDIALOG:
      SetFocus(GetDlgItem(hdlg, 100));
      CheckRadioButton(hdlg, 100, 101, 101);
      return FALSE;
     case WM_COMMAND:
      switch (GET_WM_COMMAND_ID(wParam, lParam)) {
      case 100:
      case 101:
        CheckRadioButton(hdlg, 100, 101,
                         GET_WM_COMMAND_ID(wParam, lParam));
        break;
      case IDCANCEL: EndDialog(hdlg, 0); break;
      }
     }
     return FALSE;
    }
    
    int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
                       LPSTR lpCmdLine, int nShowCmd)
    {
     DialogBox(hinst, MAKEINTRESOURCE(1), nullptr, DlgProc);
     return 0;
    }
    

    Observe that we set focus to the first button but check the second button. When the dialog regains focus, the second button will fire a WM_COMMAND because it thinks it was clicked on, and in response the dialog box moves the selection to the second button.

    The fix here is actually pretty simple: Let the dialog manager handle the initial focus. Just delete the Set­Focus call and return TRUE, which means, "Hey, dialog manager, you do the focus thing, don't worry about me."

    Another fix is to remove the code that updates the radio buttons in response to the WM_COMMAND message. (I.e., get rid of the entire case 100 and case 101 handlers.) Again, just let the dialog manager do the usual thing, and everything will work out just fine.

    It's great when you can fix a bug by deleting code.

  • The Old New Thing

    Dialog boxes return focus to the control that had focus when you last switched away; how do I get in on that action for my own windows?

    • 16 Comments

    When you switch away from a dialog box, and then switch back to the dialog box, focus returns to the control that had focus when you last left the dialog box. But if you have a window that manually hosts two controls, then when the user switches away from your window, and then switches back, focus goes to, um...

    Let's find out what happens! Take our scratch program and make these changes.

    HWND g_hwndChild2;
    
    void
    OnSize(HWND hwnd, UINT state, int cx, int cy)
    {
     // if (g_hwndChild) {
     //    MoveWindow(g_hwndChild, 0, 0, cx, cy, TRUE);
     // }
    }
    
    BOOL
    OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
    {
     g_hwndChild = CreateWindow(TEXT("button"), TEXT("&1"),
                                WS_CHILD | WS_VISIBLE |
                                WS_TABSTOP | BS_PUSHBUTTON,
                                0, 0, 100, 100,
                                hwnd, nullptr, g_hinst, 0);
     g_hwndChild2 = CreateWindow(TEXT("button"), TEXT("&2"),
                                WS_CHILD | WS_VISIBLE |
                                WS_TABSTOP | BS_PUSHBUTTON,
                                100, 0, 100, 100,
                                hwnd, nullptr, g_hinst, 0);
     return TRUE;
    }
    
    // message loop
    
     while (GetMessage(&msg, NULL, 0, 0)) {
      if (IsDialogMessage(hwnd, &msg)) continue;
      TranslateMessage(&msg);
      DispatchMessage(&msg);
     }
    

    Run the program, and the first thing you notice is that neither button has keyboard focus. Focus is on the frame window, not that that helps you much, since the frame window ignores keyboard input.

    Well, anyway, hit the Tab key to put focus on one of the buttons, then switch away to some other application, then switch back via Alt+Tab or clicking on the taskbar button. (Just don't click on the window itself, because that would interfere with the experiment, since the click also sets focus to the window you clicked on.)

    Again, focus is not on either button because it's on the frame window.

    Focus is on the frame window because nobody bothered to put it anywhere else. Let's fix that. Let's say that focus goes to the first child button when the user activates the main frame window.

    void OnActivate(HWND hwnd, UINT state,
                    HWND hwndActDeact, BOOL fMinimized)
    {
     if (state != WA_INACTIVE && !fMinimized) {
      SetFocus(g_hwndChild);
     }
    }
    
     HANDLE_MSG(hwnd, WM_ACTIVATE, OnActivate);
    

    There's a little gotcha here: We don't want to do this when minimized. When the window is activated while minimized, the user can't see any of the child windows, so putting focus on the child causes the user's keypresses to start doing invisible things. (If the user hits the space bar, it will push the invisible button!) Instead, focus should stay on the frame window. It is not well-known, but if you hit the space bar when focus is on a minimized window, it will open the system menu. Keeping focus on the frame when minimized preserves this behavior.

    Okay, at least this time, focus goes somewhere when the user activates our window. Of course, it would be better if we restored focus to where it was when the user last used our window. (For one thing, it means that the default pushbutton effect is more likely to remain correct!) If we don't know where to restore the focus to, then we fall back to using the first child window.

    HWND g_hwndLastFocus;
    void OnActivate(HWND hwnd, UINT state,
                    HWND hwndActDeact, BOOL fMinimized)
    {
     if (!fMinimized) {
      if (state == WA_INACTIVE) {
       HWND hwndFocus = GetFocus();
       if (hwndFocus && IsChild(hwnd, hwndFocus)) {
           g_hwndLastFocus = hwndFocus;
       }
      } else {
       SetFocus(g_hwndLastFocus ? g_hwndLastFocus
                                : g_hwndChild);
      }
     }
    }
    
     HANDLE_MSG(hwnd, WM_ACTIVATE, OnActivate);
    

    The basic idea is that when the window is deactivated, we remember the window that had focus, and when the window is reactivated, we restore the focus to that same window (or to our first child if we don't know what the previous focus was).

    Again, it's important to watch out for the minimized window case. If the window is minimized when the user deactivates it, we would end up saving the frame window for future restoration, when in fact we should just ignore the entire interaction while minimized.

    Note that even when not minimized, we do not try to save focus if it belongs to something outside our frame window. For our simple program, this is more of a safety check than something we expect to happen.

    Next time, we'll see an unexpected consequence of this auto-restore behavior.

  • The Old New Thing

    The code names for various subprojects within Windows 95

    • 25 Comments

    Most people know that Windows 95 was code-named Chicago. The subprojects of Windows 95 also had their code names, in part because code names are cool, and in part because these projects were already under way by the time somebody decided to combine them into one giant project.

    Component Code Name
    16-bit DOS kernel Jaguar
    32-bit DOS kernel Cougar
    Win32 kernel Panther
    User interface Stimpy

    Even when they were separate projects, the first three teams worked closely together, so the names followed a pattern of ferocious cats. My guess is that when the user interface team chose their code name, they heard that the other guys were naming themselves after cats, so they picked a cat, too.

    I don't know whether they did that on purpose or by accident, but the cat they picked was not ferocious at all. Instead, they picked a cartoon cat.

    Bonus trivia: When the feature to show a special message after Windows had shut down was first added, the shutdown bitmap was a screen shot of Ren and Stimpy saying good-bye. Fortunately, we remembered to replace them before shipping.

    If you were paying attention: You would have noticed that code names get reused a lot, not because of any connection between the projects but purely by coincidence.

Page 6 of 427 (4,267 items) «45678»