Menu

#401 Ill conceived PRECONDITION in TDC::ExtTextOut (regression in 6.32)

6.44
closed
1
2026-04-03
2018-03-28
No

The TDC::ExtTextOut documentation states that the string length (respectively the parameter "count") can be given as -1 in which case the whole string shall be written. This is fine as such because it makes the OWLNext API more regular than the bare Windows API wich does allow "-1" only for some text drawing functions (ExtTextOut not among them).

The implementation is wrong though. The TDC::ExtTextOut implementation contains

:::C++
PRECONDITION(count == 0 || str.length() > 0);

That condition is triggered if count is -1 and the string is empty. I believe this PRECONDITION can be removed.

Another thing would be to test whether the string exceeds 8192 characters because the Windows API documentation for ExtTextOut disallows this. I do not know what happens if the string is longer.

Also, one more issue in the documentation of TDC::ExtTextOut: It contains the fragment "Draws up to count characters of the given null-terminated string". But the Windows API documentation emphasizes that the string does not need to be null-terminated. In my opinion OWLNext should follow that example and not imply that the string is null-terminated. However I do not know what happens if the string contains a null-byte in the middle.

Related

Wiki: OWLNext_Stable_Releases

Discussion

  • Vidar Hasfjord

    Vidar Hasfjord - 2018-03-29
    • labels: Crash --> Crash, API, Strings
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -1,12 +1,15 @@
    -The documentation for TDC::ExtTextOut states that the string length (respectively the parameter "count") can be given as -1 in which case the whole string shall be written. This is fine as such because it makes the OWL-API more regular than the bare Windows-API wich does allow "-1" only for some text drawing functions (ExtTextOut not among them).
    +The [TDC::ExtTextOut documentation](http://owlnext.sourceforge.net/help/html/dc/d23/classowl_1_1_t_d_c.html#acf7015045802386ea381daffcf3664e3) states that the string length (respectively the parameter "count") can be given as -1 in which case the whole string shall be written. This is fine as such because it makes the OWLNext API more regular than the bare Windows API wich does allow "-1" only for some text drawing functions (ExtTextOut not among them).
    
    -The implementation is wrong though:
    -TDC::ExtTextOut contains
    +The implementation is wrong though. The [TDC::ExtTextOut implementation](https://sourceforge.net/p/owlnext/code/4130/tree/trunk/source/owlcore/dc.cpp#l581) contains
    +
    +~~~
    +:::C++
     PRECONDITION(count == 0 || str.length() > 0);
    -.
    +~~~
    +
     That condition is triggered if count is -1 and the string is empty. I believe this PRECONDITION can be removed.
    
    -Another thing would be to test whether the string exceeds 8192 characters because the Windows API disallows this. I do not know what happens if the string is longer.
    +Another thing would be to test whether the string exceeds 8192 characters because the Windows API documentation for [ExtTextOut](https://msdn.microsoft.com/en-us/library/dd162713.aspx) disallows this. I do not know what happens if the string is longer.
    
    -Also, on more issue in the documentation of TDC::ExtTextOut: It contains the fragment
    -"Draws up to count characters of the given null-terminated string". But the Windows-API documentation emphasizes that the string does not need to be null-terminated. In my opinion Owlnext should follow that example and not imply that the string is null-terminated. However I do not know what happens if the string contains a null-byte in the middle.
    +Also, one more issue in the documentation of TDC::ExtTextOut: It contains the fragment
    +"Draws up to count characters of the given null-terminated string". But the Windows API documentation emphasizes that the string does not need to be null-terminated. In my opinion OWLNext should follow that example and not imply that the string is null-terminated. However I do not know what happens if the string contains a null-byte in the middle.
    
    • assigned_to: Vidar Hasfjord
    • Group: unspecified --> 6.44
     
  • Vidar Hasfjord

    Vidar Hasfjord - 2018-03-29

    Hi Volker, thanks for reporting this.

    It is a slight regression of mine in 6.32 [r793] as part of the string-aware additions to OWLNext. The old version checked for a null-pointer str argument, while the new string-aware version changed that to a check for str.length() > 0. This is really not equivalent. There is no way to pass a null-string now, and as you say, the assertion is no longer needed.

    Another thing would be to test whether the string exceeds 8192 characters

    Agree. We should assert this, as it is a requirement of the underlying API.

    the Windows API documentation emphasizes that the string does not need to be null-terminated. In my opinion OWLNext should follow that example and not imply that the string is null-terminated.

    Here, the string returned by str.c_str is guaranteed to be null-terminated by the C++ standard. However, there is a related issue: What happens if you provide a count greater than the length of the string? As you say, the Windows API does not require null-termination, so it cannot test for this. However, we can do so now, since we use a string type with length. Hence, I propose we change the assertion to:

    :::C++
    PRECONDITION(count <= std::min(static_cast<int>(str.length()), 8192));
    

    However I do not know what happens if the string contains a null-byte in the middle.

    Test it! My guess is that it is truncated. However, this is purely a behavioural issue, not consequential to the assertion that we operate within the bounds of the string. Perhaps, it should be pointed out in the documentation, though, that a string containing a null-byte will be truncated, if that is the case.

     

    Related

    Commit: [r793]

  • Vidar Hasfjord

    Vidar Hasfjord - 2018-03-29
    • summary: Ill conceived PRECONDITION in TDC::ExtTextOut --> Ill conceived PRECONDITION in TDC::ExtTextOut (regression in 6.32)
    • status: open --> pending
     

    Last edit: Vidar Hasfjord 2018-03-29
  • Vidar Hasfjord

    Vidar Hasfjord - 2018-03-29

    This issue was fixed on the trunk in [r4131]. I also improved the documentation to point out that 8192 is the max count, and I also included a link to the Windows API documentation. Please review. If OK, I will merge it into 6.44.

    Note that this is a partial fix of the regression. The issue that TDC::ExtTextOut no longer supports non-null-terminated strings is still unresolved. This issue also applies to similar functions in TDC having the character count as a parameter. It can be circumvented by using the bare Windows API, or by creating a temporary string as follows:

    :::C++
    // Before: dc.ExtTextOut(p, opt, r, ptr, count);
    // Note: ptr is pointing into a non-null-terminated buffer.
    //
    dc.ExtTextOut(p, opt, r, tstring(ptr, count));
    
    // In C++11, this can be simplified using an initializer list.
    //
    dc.ExtTextOut(p, opt, r, {ptr, count});
    

    For the future, we may consider supporting std::string_view (C++17) for a more efficient solution.

    I have updated Strings in OWLNext about this issue.

    PS. Also see [feature-requests:#127] "Support for string_view".

     

    Related

    Commit: [r4131]
    Feature Requests: #127
    Wiki: Strings_in_OWLNext


    Last edit: Vidar Hasfjord 2018-03-29
  • Vidar Hasfjord

    Vidar Hasfjord - 2018-03-29

    Hi Volker,

    I have now added you as a Developer on the OWLNext SourceForge project, so that you can more directly contribute to the code, wiki, etc. See [discussion:c8848884].

     

    Related

    Discussion: c8848884

  • Vidar Hasfjord

    Vidar Hasfjord - 2018-03-30

    The fix for this issue has now been merged into Owlet [r4134] and 6.44 [r4135].

     

    Related

    Commit: [r4134]
    Commit: [r4135]

  • Vidar Hasfjord

    Vidar Hasfjord - 2018-03-30
    • Status: pending --> closed
     
  • Vidar Hasfjord

    Vidar Hasfjord - 2026-04-03
    • labels: Crash, API, Strings --> Crash, API, Strings, Regression
     
  • Vidar Hasfjord

    Vidar Hasfjord - 2026-04-03

    The fix for this issue was released in OWLNext 6.44.2.

     

Log in to post a comment.

MongoDB Logo MongoDB