Menu

#656 Fixed many many many bugs.

Next_major_release
accepted
nobody
None
7
2015-04-19
2015-03-12
No

I fixed a very large number of issues, from buffer overruns to format string errors. This should be a no-brainer.

1 Attachments

Discussion

1 2 > >> (Page 1 of 2)
  • Don HO

    Don HO - 2015-03-12
    • status: open --> accepted
    • Priority: 5 --> 7
     
  • Don HO

    Don HO - 2015-03-12

    Thank you Alexander,

    I got REJECTED PATCH HUNKS message for each patch.
    Any idea about that?

    Don

     
  • Alexander Riccio

    Ah, I think I know what the problem is, (it's my fault, not used to diff/patch).

    I tried it myself, and patch failed, as it couldn't find the file. Duh.

    I kept the modified version in a folder called patched, and the original in original, and diff stored this. Revert all changes made to the directory (if there were any), and try the attached patch. It's been patched (yeah, a patched patch).

     
  • Alexander Riccio

    I've also attached the successful output of applying the patch.

     
  • Don HO

    Don HO - 2015-03-13

    The latest patch you submitted still doesn't work for me (the same error).
    It seems to me the absolute path are used.
    Have you tried to rename your folder before applying the patch?

    Don

     
  • Alexander Riccio

    How are you applying the patch? It sounds like your using TortoiseSVN? If you're using good ol' patch, could you post the (failing) output with --verbose?

    Yeah, I tried renaming the folder. Everything is good on my end.

     
  • Don HO

    Don HO - 2015-03-14

    Yes, I'm using TortoiseSVN with GUI.
    After applying your patch on directory "trunk", a "patch" directory is created with the sub-directory (see attached file), and they are all empty.

    I test with patch 633, works fine for me:
    https://sourceforge.net/p/notepad-plus/patches/633/

     
  • Don HO

    Don HO - 2015-03-14

    And when I try to preview patched file. It shows me "Rejected patch hunks for ..." on the title bar (see attached file)

     

    Last edit: Don HO 2015-03-14
  • Don HO

    Don HO - 2015-03-14

    Alexander,

    After struggling during 1 hour with the patch, I quit.
    Please attach your zipped source code, then I will merge manually.

    Don

     
  • Alexander Riccio

    Hmm, it seems to understand the pat, as indicated by the screenshot, so I'm stumped there. Sorry to make you struggle. I'll post that zip file.

     
  • Alexander Riccio

    Alrighty, here it is.

     
  • Don HO

    Don HO - 2015-03-14

    Thank you Alexander. It's in SVN now.

    Don

     

    Last edit: Don HO 2015-03-15
  • Don HO

    Don HO - 2015-03-14

    Could you do a summary (+ small explanation) about your patch, which will be the guideline for coding Notepad++?

    Thank you
    Don

     
  • Alexander Riccio

    Thank you Alexander. It's in SVN now.

    Yay!

    Could you do a summary (+ small explanation) about your patch, which will be the guideline for coding Notepad++?

    A summary? Sure!

    What exactly do you mean by coding guideline?

     
    • Don HO

      Don HO - 2015-03-15

      Example of summary:
      1. Initialize the local character array with empty string: explanation...
      2. use %u instead of %d when variable is unsigned int: explanation...
      3. ...

      The coding guideline is rather for me to avoid such errors in the future.

       
      • Menno Vogels

        Menno Vogels - 2015-03-15
         
        • Alexander Riccio

           

          Last edit: Alexander Riccio 2015-03-16
      • Alexander Riccio

        Actually, the two biggest things you can do are not even coding guidelines:

        1. Use the built in visual studio code analysis tools; because vc120_xp, for some weird reason, doesn't support code analysis, what I do is create a separate build configuration (e.g. "Unicode Static Analysis"), and build that config. You'll also need to disable precompiled headers for this config, else the compiler will crash/hit an Internal Compiler Error. This patch was the result of such a build.

        2. Configure your own installation of Notepad++ to run under Application Verifier. Application Verifier cones with the Windows SDK and is a truly enlightening tool, which catches an incredible number of bugs at runtime, without recompilation/instrumentation. I've found bugs in everything from VLC & Git, to Notepad++ itself, this way. Open Application Verifier, add Notepad++ (under file), and in addition to the default checks, enable DirtyStacks (under miscellaneous), and in the properties for Heaps (under basics), enable: "Address", "Protect", "Size", & "LFH guard pages". Now, many bugs will show up immediately, at the offending instruction. For example: if Notepad++ overwrites a buffer (by more than ~4 bytes), it'll touch the next page, and trigger an access violation. If Notepad++ tries to use memory after freeing it, Application Verifier will trigger a debug break. If Notepad++ passes an invalid HANDLE to a system function, Application Verifier will trigger a debug break.

        There are two downsides to using Application Verifier:

        1. The instance of Notepad++ under test will suffer a performance hit; which won't be a real problem, because it's already very fast ;)
        2. If it's not running under a debugger, Notepad++ will just crash. If you have full memory dumps enabled, opening in WinDbg & running !analyze -v will probably tell you exactly what the problem is.

        Other good practices:

        1. For C-style strings, prefer PTSTR/PCTSTR over TCHAR*/const TCHAR*. PTSTR has special meaning for the static analyzer - it means 'pointer to a null-terminated array of characters', which thus allows it to detect misuse of any standard-library functions that expect null terminated strings.
        2. Any function that writes too a buffer (passed as a pointer), should require a parameter that describes the size of the buffer.
        3. When writing string handling functions, in addition to #1, SAL annotate function parameters. I'll admit, SAL annotated code looks absolutely horrible at first, but it is infinitely useful for string/buffer handling. In fact, Microsoft invented it to detect and prevent string handling issues, which are (nearly always) security issues. For example, if you're writing a function that writes a null-terminated string to a buffer (passed as a pointer), use _Out_z_, or when following #2, use _Out_writes_z_( sizeOfBuffer ). Similarly, for a function that expects a pointer-to-a-null-terminated string as a parameter, and reads from it, mark the parameter _In_z_.
        4. When writing functions that read-from/write-to a buffer, which accept a pointer to the first element, annotate that pointer to describe valid bounds. For reading from, the correct annotation is _In_reads_( sizeOfBuffer ). For writing to, it's _Out_writes_( sizeOfBuffer ).
        5. Parameters & variables that describe the size of an object or buffer should use the type rsize_t. This one's actually a CERT standard.
        6. For functions that return a success or failure code, annotate the successful condition. SAL has a handy annotation that greatly aids in detecting use of invalid _Out_ parameters, _Success_( someCondition ). So for a function that returns NULL on failure, the annotation would be _Success_( return != NULL ), and is placed before the functions return type.
        7. Use const like you get paid every time you type those 5 characters. Ok, this isn't a string handling thing, I'm just a total const nazi.
        8. Zero-initialize string buffers. Thus is not strictly necessary, but might limit the damage done by dangerous APIs.
        9. never ever ever ever EVER use lstrcpy. Ever. Or any other function that blindly swallows SEH exceptions. Seriously. Not kidding about this.

        Once again I'll admit, SAL can make your function declarations much longer, and uglier, but once you're past that, they're self-documenting, and a huge benefit to static analysis.

         

        Last edit: Alexander Riccio 2015-03-16
        • Alexander Riccio

          A few other rules that I've thought of while writing patch 662.

          continue list here:

          1. Never ever ever ignore return values, even if the function looks like it should never fail. Especially if it looks like it should never fail. Checking return values is not optional! If program correctness was optional, then checking return values would be optional! If program correctness was optional, then we could make Notepad++ arbitrarily small, and arbitrarily fast!
          2. Don't catch or throw SEH exceptions. They're almost never recoverable, and the best thing to do is crash & burn.
          3. Don't MIX C++ and SEH exceptions. There's a particularly egregious example in FileManager::loadFileData - Notepad++ throws an "empty" C++ exception, INSIDE an SEH block. Figuring out what the hell was going on here was a real pain - an empty C++ exception is technically a call to std::terminate( ), but catching it with SEH seems to stop this. Even worse, this isn't any kind of known SEH exception, so I couldn't match it up with any documented SEH exception. I even wrote a filter that had a HUGE switch/case construct that handled every single known SEH exception, and it still fell through to the default case. Please don't do that to anybody - it's cruel!
          4. Throw and catch ONLY the most specific exceptions! catch(...) is the worst offender. If you can't predict the exception, then there is certainly a bug! In #662, I changed FileManager::LoadFileData to throw (and catch) a std::bad_alloc on SC_STATUS_BADALLOC - which clearly documents intent - but also to throw a generic std::exception on SC_STATUS_FAILURE, which is NOT expected, and generally bad news. Stack unwinding is probably the best option on SC_STATUS_FAILURE.

          ...a few more to come tomorrow, it's time for bed!

           
      • Menno Vogels

        Menno Vogels - 2015-03-16

        For who is interested: Source-code Annotation Language (SAL)

        +100 on using const and NOT using the lstr-functions!

         

        Last edit: Menno Vogels 2015-03-16
        • Alexander Riccio

           
        • Alexander Riccio

          I should also qualify that my const-nazism really does border on straight up insanity. I mean, look at this crazy shit: https://github.com/ariccio/altWinDirStat/blob/master/WinDirStat/windirstat/TreeListControl.h#L315

          Yes, those are const-pointers-to-const, on a const method.

           

          Last edit: Alexander Riccio 2015-03-16
          • Menno Vogels

            Menno Vogels - 2015-03-16

            NICE!

            LOL --> "macros_that_scare_small_children.h"

             
            • Alexander Riccio

              Yeah, I totally stole that from Google's C++ style guide :)

              Side note: I learned a LOT by poking around the Chromium sources.

               

              Last edit: Alexander Riccio 2015-03-16
  • Alexander Riccio

    As a sidenote: how many Notepad++ users actually run Notepad++ on Windows XP? I'd happily rewrite all of the string formatting functions to use their bounds-checked/Strsafe equivalents, but vc120_xp doesn't support any of them.

     
1 2 > >> (Page 1 of 2)