diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2016-10-28 21:42:42 +0000 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2016-10-28 21:42:42 +0000 |
| commit | 2c043fb5b31839d7f7430cb410e175d2945acbe3 (patch) | |
| tree | 1fc82606cac66735e2c299f6d0e46b4ee027afff /fluid | |
| parent | 4567268d2a72a88ea812aa685333e7eee113ca86 (diff) | |
Fix string truncation in fluid (STR #2722 continued).
This commit fixes the truncated string drawing that was partly fixed
in svn r 9112 (FLTK 1.3.1, 2011-10-01).
Combined port of svn r 12057 and 12059. The latter adds sanity checks
and fixes potential buffer overflows.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@12060 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'fluid')
| -rw-r--r-- | fluid/Fl_Type.cxx | 97 |
1 files changed, 49 insertions, 48 deletions
diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx index db5e04c2b..48881836c 100644 --- a/fluid/Fl_Type.cxx +++ b/fluid/Fl_Type.cxx @@ -166,6 +166,43 @@ extern int show_comments; //////////////////////////////////////////////////////////////// +// Copy the given string str to buffer p with no more than maxl characters. +// Add "..." if string was truncated. +// If parameter quote is true (not 0) the string is quoted with "". +// Quote characters are NOT counted. +// The returned buffer (string) is terminated with a null byte. +// Returns pointer to end of string (before terminating null byte). +// Note: the buffer p must be large enough to hold (4 * (maxl+1) + 1) bytes +// or (4 * (maxl+1) + 3) bytes if quoted, e.g. "123..." because each UTF-8 +// character can consist of 4 bytes, "..." adds 3 bytes, quotes '""' add two +// bytes, and the terminating null byte adds another byte. +// This supports Unicode code points up to U+10FFFF (standard as of 10/2016). +// Sanity checks for illegal UTF-8 sequences are included. + +static char *copy_trunc(char *p, const char *str, int maxl, int quote) { + + int size = 0; // truncated string size in characters + int bs; // size of UTF-8 character in bytes + const char *end = str + strlen(str); // end of input string + if (quote) *p++ = '"'; // opening quote + while (size < maxl) { // maximum <maxl> characters + if (!(*str & (-32))) break; // end of string (0 or control char) + bs = fl_utf8len(*str); // size of next character + if (bs <= 0) break; // some error - leave + if (str + bs > end) break; // UTF-8 sequence beyond end of string + while (bs--) *p++ = *str++; // copy that character into the buffer + size++; // count copied characters + } + if (*str) { // string was truncated + strcpy(p,"..."); p += 3; + } + if (quote) *p++ = '"'; // closing quote + *p = 0; // terminating null byte + return p; +} + +//////////////////////////////////////////////////////////////// + class Widget_Browser : public Fl_Browser_ { friend class Fl_Type; @@ -287,6 +324,8 @@ void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const { // cast to a more general type Fl_Type *l = (Fl_Type *)v; + char buf[340]; // edit buffer: large enough to hold 80 UTF-8 chars + nul + // calculate the horizontal start position of this item // 3 is the edge of the browser // 13 is the width of the arrow that indicates children for the item @@ -302,14 +341,7 @@ void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const { // line inside this browser line int comment_incr = 0; if (show_comments && l->comment()) { - char buf[82], *d = buf; - const char *s = l->comment(); - for (int i=0; i<80; i++) { - char c = *s++; - if (c==0 || c=='\n') break; - *d++ = c; - } - *d = 0; + copy_trunc(buf, l->comment(), 80, 0); comment_incr = textsize()-1; if (l->new_selected) fl_color(fl_contrast(FL_DARK_GREEN,FL_SELECTION_COLOR)); else fl_color(fl_contrast(FL_DARK_GREEN,color())); @@ -367,31 +399,12 @@ void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const { if (c) { fl_font(textfont()|FL_BOLD, textsize()); fl_draw(c, X, Y+13); - } else if ((c=l->label())) { - char buf[100]; char* p = buf; - *p++ = '"'; - int b,l=strlen(c); // size in bytes - for (int i = 20; i>0;i--) { // maximum 20 characters - if (*c==0) break; // end of string - fl_utf8decode(c, c+l, &b); // b=size of char in bytes - if (b==-1) break; // some error - leave - l-=b; // l = bytes left in string - while (b--)*p++ = *c++; // copy that character into the buffer - } - if (*c) {strcpy(p,"..."); p+=3;} // there would be more to this string - *p++ = '"'; - *p = 0; + } else if ((c = l->label())) { + copy_trunc(buf, c, 20, 1); // quoted string fl_draw(buf, X, Y+13); } } else { - const char* c = l->title(); - char buf[60]; char* p = buf; - for (int i = 55; i--;) { - if (! (*c & -32)) break; - *p++ = *c++; - } - if (*c) {strcpy(p,"..."); p+=3;} - *p = 0; + copy_trunc(buf, l->title(), 55, 0); fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize()); fl_draw(buf, X, Y+13); } @@ -405,6 +418,9 @@ void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const { } int Widget_Browser::item_width(void *v) const { + + char buf[340]; // edit buffer: large enough to hold 80 UTF-8 chars + nul + Fl_Type *l = (Fl_Type *)v; if (!l->visible) return 0; @@ -420,27 +436,12 @@ int Widget_Browser::item_width(void *v) const { if (c) { fl_font(textfont()|FL_BOLD, textsize()); W += int(fl_width(c)); - } else if ((c=l->label())) { - char buf[50]; char* p = buf; - *p++ = '"'; - for (int i = 20; i--;) { - if (! (*c & -32)) break; - *p++ = *c++; - } - if (*c) {strcpy(p,"..."); p+=3;} - *p++ = '"'; - *p = 0; + } else if (l->label()) { + copy_trunc(buf, l->label(), 20, 1); // quoted string W += int(fl_width(buf)); } } else { - const char* c = l->title(); - char buf[60]; char* p = buf; - for (int i = 55; i--;) { - if (! (*c & -32)) break; - *p++ = *c++; - } - if (*c) {strcpy(p,"..."); p+=3;} - *p = 0; + copy_trunc(buf, l->title(), 55, 0); fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize()); W += int(fl_width(buf)); } |
