Changeset 2fa0237


Ignore:
Timestamp:
Sep 8, 2023, 12:46:55 AM (8 months ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
master
Children:
553f032f
Parents:
3ee8853
Message:

Fix cstring input length interpretation issue that had a buffer overflow case.

The cases added to the manipulatorsInput test are runnable against an old libcfa build. In this setup, the test fails with an illustration of the bug.

The testing in this commit drives the following inputs through a length-8 buffer.

  • 123456
  • 123456789

The obviously-missing cases, like 1234567, will be added later.
They will accompany fixes for further bugs not solved yet.

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/iostream.cfa

    r3ee8853 r2fa0237  
     1
    12//
    23// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     
    976977                if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; }
    977978                // no maximum width necessary because text ignored => width is read width
    978                 if ( f.wd != -1 ) { start += sprintf( &fmtstr[start], "%d", f.wd ); }
     979                if ( f.wd != -1 ) {
     980                        // wd is buffer bytes available (for input chars + null terminator)
     981                        // rwd is count of input chars
     982                        int rwd = f.flags.rwd ? f.wd : (f.wd - 1);
     983                        start += sprintf( &fmtstr[start], "%d", rwd );
     984                }
    979985
    980986                if ( ! scanset ) {
     
    993999                } // if
    9941000
    995                 int check = f.wd - 1;
     1001                int check = f.wd - 2;
    9961002                if ( ! f.flags.rwd ) f.s[check] = '\0';                 // insert sentinel
    9971003                len = fmt( is, fmtstr, f.s );
  • tests/io/.expect/manipulatorsInput.arm64.txt

    r3ee8853 r2fa0237  
     1pre1 "123456", canary ok
     2pre2a "1234567", exception occurred, canary ok
     3pre2b "89", canary ok
    141 yyyyyyyyyyyyyyyyyyyy
    252 abcxxx
  • tests/io/.expect/manipulatorsInput.x64.txt

    r3ee8853 r2fa0237  
     1pre1 "123456", canary ok
     2pre2a "1234567", exception occurred, canary ok
     3pre2b "89", canary ok
    141 yyyyyyyyyyyyyyyyyyyy
    252 abcxxx
  • tests/io/.expect/manipulatorsInput.x86.txt

    r3ee8853 r2fa0237  
     1pre1 "123456", canary ok
     2pre2a "1234567", exception occurred, canary ok
     3pre2b "89", canary ok
    141 yyyyyyyyyyyyyyyyyyyy
    252 abcxxx
  • tests/io/.in/manipulatorsInput.txt

    r3ee8853 r2fa0237  
     1123456
     2123456789
    13abc
    24abc
  • tests/io/manipulatorsInput.cfa

    r3ee8853 r2fa0237  
    1515
    1616int main() {
     17        {
     18                // Upfront checks to ensure buffer safety.  Once these pass, the simpler `wdi(sizeof(s),s)`
     19                // usage, as in the scanf alignment cases below, is justified.
     20                struct {
     21                        char buf[8];
     22                        char canary;
     23                } data;
     24                static_assert( sizeof(data.buf) == 8 );
     25                static_assert( &data.buf[8] == &data.canary );  // canary comes right after buf
     26
     27                void rep(const char* casename) {
     28                        data.canary = 42;
     29                        bool caught = false;
     30                        try {
     31                                sin | wdi( sizeof(data.buf), data.buf );
     32                        } catch (cstring_length*) {
     33                                caught = true;
     34                        }
     35                        printf( "%s \"%s\"", casename, data.buf );
     36                        if ( caught ) {
     37                                printf(", exception occurred");
     38                        }
     39                        if ( data.canary == 42 ) {
     40                                printf(", canary ok");
     41                        } else {
     42                                printf(", canary overwritten to %d", data.canary);
     43                        }
     44                        printf("\n");
     45                }
     46
     47                rep("pre1");
     48                rep("pre2a");
     49                rep("pre2b");
     50                scanf("\n");  // next test does not start with %s so does not tolerate leading whitespace
     51        }
    1752        {
    1853                char s[] = "yyyyyyyyyyyyyyyyyyyy";
Note: See TracChangeset for help on using the changeset viewer.