Ticket #4174: 0001-Improve-safety-of-previous-char-fetching-string-func.2.patch

File 0001-Improve-safety-of-previous-char-fetching-string-func.2.patch, 23.4 KB (added by psprint, 3 years ago)

make indent

  • lib/strutil.h

    From 2456318bbe0ce49b4c235007d75c7186a3a42799 Mon Sep 17 00:00:00 2001
    From: Sebastian Gniazdowski <sgniazdowski@gmail.com>
    Date: Wed, 13 Jan 2021 22:00:56 -0600
    Subject: [PATCH] Improve safety of previous char fetching string functions.
    
    ---
     lib/strutil.h               | 30 ++++++++---------
     lib/strutil/strutil.c       | 32 +++++++++---------
     lib/strutil/strutil8bit.c   |  4 ++-
     lib/strutil/strutilascii.c  |  4 ++-
     lib/strutil/strutilutf8.c   | 34 ++++++++++++++++---
     lib/widget/input.c          | 30 ++++++++++++-----
     lib/widget/input_complete.c | 65 ++++++++++++++++++++++++-------------
     src/help.c                  |  3 +-
     src/usermenu.c              | 46 ++++++++++++++------------
     9 files changed, 156 insertions(+), 92 deletions(-)
    
    diff --git a/lib/strutil.h b/lib/strutil.h
    index a091c25aa..667f7df2e 100644
    a b struct str_class 
    110110    gboolean (*is_valid_string) (const char *); 
    111111      /*I*/ int (*is_valid_char) (const char *, size_t); 
    112112      /*I*/ void (*cnext_char) (const char **); 
    113     void (*cprev_char) (const char **); 
     113    void (*cprev_char) (const char **, const char *begin); 
    114114    void (*cnext_char_safe) (const char **); 
    115       /*I*/ void (*cprev_char_safe) (const char **); 
     115      /*I*/ void (*cprev_char_safe) (const char **, const char *begin); 
    116116      /*I*/ int (*cnext_noncomb_char) (const char **text); 
    117117      /*I*/ int (*cprev_noncomb_char) (const char **text, const char *begin); 
    118118      /*I*/ gboolean (*char_isspace) (const char *); 
    int str_is_valid_char (const char *ch, size_t size); 
    262262char *str_get_next_char (char *text); 
    263263const char *str_cget_next_char (const char *text); 
    264264 
    265 /* return previous characters before text, do not call on the start of strings 
     265/* return previous characters before text 
    266266 */ 
    267 char *str_get_prev_char (char *text); 
    268 const char *str_cget_prev_char (const char *text); 
     267char *str_get_prev_char (char *text, const char *begin); 
     268const char *str_cget_prev_char (const char *text, const char *begin); 
    269269 
    270270/* set text to next characters, do not call on the end of string 
    271271 */ 
    272272void str_next_char (char **text); 
    273273void str_cnext_char (const char **text); 
    274274 
    275 /* set text to previous characters, do not call on the start of strings 
     275/* set text to previous characters 
    276276 */ 
    277 void str_prev_char (char **text); 
    278 void str_cprev_char (const char **text); 
     277void str_prev_char (char **text, const char *begin); 
     278void str_cprev_char (const char **text, const char *begin); 
    279279 
    280280/* return next characters after text, do not call on the end of string 
    281281 * works with invalid string  
    void str_cprev_char (const char **text); 
    284284char *str_get_next_char_safe (char *text); 
    285285const char *str_cget_next_char_safe (const char *text); 
    286286 
    287 /* return previous characters before text, do not call on the start of strings 
    288  * works with invalid string  
     287/* return previous characters before text, works with invalid string 
    289288 * I 
    290289 */ 
    291 char *str_get_prev_char_safe (char *text); 
    292 const char *str_cget_prev_char_safe (const char *text); 
     290char *str_get_prev_char_safe (char *text, const char *begin); 
     291const char *str_cget_prev_char_safe (const char *text, const char *begin); 
    293292 
    294293/* set text to next characters, do not call on the end of string 
    295294 * works with invalid string  
    const char *str_cget_prev_char_safe (const char *text); 
    298297void str_next_char_safe (char **text); 
    299298void str_cnext_char_safe (const char **text); 
    300299 
    301 /* set text to previous characters, do not call on the start of strings 
    302  * works with invalid string  
     300/* set text to previous characters, works with invalid string 
    303301 * I 
    304302 */ 
    305 void str_prev_char_safe (char **text); 
    306 void str_cprev_char_safe (const char **text); 
     303void str_prev_char_safe (char **text, const char *begin); 
     304void str_cprev_char_safe (const char **text, const char *begin); 
    307305 
    308306/* set text to next noncombining characters, check the end of text 
    309307 * return how many characters was skipped 
  • lib/strutil/strutil.c

    diff --git a/lib/strutil/strutil.c b/lib/strutil/strutil.c
    index cf11d00d8..937256260 100644
    a b str_cnext_char (const char **text) 
    507507/* --------------------------------------------------------------------------------------------- */ 
    508508 
    509509char * 
    510 str_get_prev_char (char *text) 
     510str_get_prev_char (char *text, const char *begin) 
    511511{ 
    512     used_class.cprev_char ((const char **) &text); 
     512    used_class.cprev_char ((const char **) &text, begin); 
    513513    return text; 
    514514} 
    515515 
    516516/* --------------------------------------------------------------------------------------------- */ 
    517517 
    518518const char * 
    519 str_cget_prev_char (const char *text) 
     519str_cget_prev_char (const char *text, const char *begin) 
    520520{ 
    521     used_class.cprev_char (&text); 
     521    used_class.cprev_char (&text, begin); 
    522522    return text; 
    523523} 
    524524 
    525525/* --------------------------------------------------------------------------------------------- */ 
    526526 
    527527void 
    528 str_prev_char (char **text) 
     528str_prev_char (char **text, const char *begin) 
    529529{ 
    530     used_class.cprev_char ((const char **) text); 
     530    used_class.cprev_char ((const char **) text, begin); 
    531531} 
    532532 
    533533/* --------------------------------------------------------------------------------------------- */ 
    534534 
    535535void 
    536 str_cprev_char (const char **text) 
     536str_cprev_char (const char **text, const char *begin) 
    537537{ 
    538     used_class.cprev_char (text); 
     538    used_class.cprev_char (text, begin); 
    539539} 
    540540 
    541541/* --------------------------------------------------------------------------------------------- */ 
    str_cnext_char_safe (const char **text) 
    575575/* --------------------------------------------------------------------------------------------- */ 
    576576 
    577577char * 
    578 str_get_prev_char_safe (char *text) 
     578str_get_prev_char_safe (char *text, const char *begin) 
    579579{ 
    580     used_class.cprev_char_safe ((const char **) &text); 
     580    used_class.cprev_char_safe ((const char **) &text, begin); 
    581581    return text; 
    582582} 
    583583 
    584584/* --------------------------------------------------------------------------------------------- */ 
    585585 
    586586const char * 
    587 str_cget_prev_char_safe (const char *text) 
     587str_cget_prev_char_safe (const char *text, const char *begin) 
    588588{ 
    589     used_class.cprev_char_safe (&text); 
     589    used_class.cprev_char_safe (&text, begin); 
    590590    return text; 
    591591} 
    592592 
    593593/* --------------------------------------------------------------------------------------------- */ 
    594594 
    595595void 
    596 str_prev_char_safe (char **text) 
     596str_prev_char_safe (char **text, const char *begin) 
    597597{ 
    598     used_class.cprev_char_safe ((const char **) text); 
     598    used_class.cprev_char_safe ((const char **) text, begin); 
    599599} 
    600600 
    601601/* --------------------------------------------------------------------------------------------- */ 
    602602 
    603603void 
    604 str_cprev_char_safe (const char **text) 
     604str_cprev_char_safe (const char **text, const char *begin) 
    605605{ 
    606     used_class.cprev_char_safe (text); 
     606    used_class.cprev_char_safe (text, begin); 
    607607} 
    608608 
    609609/* --------------------------------------------------------------------------------------------- */ 
  • lib/strutil/strutil8bit.c

    diff --git a/lib/strutil/strutil8bit.c b/lib/strutil/strutil8bit.c
    index fa7bbf6a4..755a66ddb 100644
    a b str_8bit_cnext_char (const char **text) 
    112112/* --------------------------------------------------------------------------------------------- */ 
    113113 
    114114static void 
    115 str_8bit_cprev_char (const char **text) 
     115str_8bit_cprev_char (const char **text, const char *begin) 
    116116{ 
    117117    (*text)--; 
     118    if (*text < begin) 
     119        *text = NULL; 
    118120} 
    119121 
    120122/* --------------------------------------------------------------------------------------------- */ 
  • lib/strutil/strutilascii.c

    diff --git a/lib/strutil/strutilascii.c b/lib/strutil/strutilascii.c
    index 7a585303e..a18d34bd7 100644
    a b str_ascii_cnext_char (const char **text) 
    8585/* --------------------------------------------------------------------------------------------- */ 
    8686 
    8787static void 
    88 str_ascii_cprev_char (const char **text) 
     88str_ascii_cprev_char (const char **text, const char *begin) 
    8989{ 
    9090    (*text)--; 
     91    if (*text < begin) 
     92        *text = NULL; 
    9193} 
    9294 
    9395/* --------------------------------------------------------------------------------------------- */ 
  • lib/strutil/strutilutf8.c

    diff --git a/lib/strutil/strutilutf8.c b/lib/strutil/strutilutf8.c
    index 5ac0015e6..37a24be62 100644
    a b str_utf8_cnext_char (const char **text) 
    117117/* --------------------------------------------------------------------------------------------- */ 
    118118 
    119119static void 
    120 str_utf8_cprev_char (const char **text) 
     120str_utf8_cprev_char (const char **text, const char *begin) 
    121121{ 
    122     (*text) = g_utf8_prev_char (*text); 
     122    (*text) = g_utf8_find_prev_char (begin, *text); 
    123123} 
    124124 
    125125/* --------------------------------------------------------------------------------------------- */ 
    str_utf8_cnext_char_safe (const char **text) 
    136136/* --------------------------------------------------------------------------------------------- */ 
    137137 
    138138static void 
    139 str_utf8_cprev_char_safe (const char **text) 
     139str_utf8_cprev_char_safe (const char **text, const char *begin) 
    140140{ 
    141141    const char *result, *t; 
    142142 
    143     result = g_utf8_prev_char (*text); 
     143    result = g_utf8_find_prev_char (begin, *text); 
     144    /* Beginning of the string reached (if NULL)? */ 
     145    if (!result) 
     146    { 
     147        *text = NULL; 
     148        return; 
     149    } 
     150 
    144151    t = result; 
    145152    str_utf8_cnext_char_safe (&t); 
    146153    if (t == *text) 
    147154        (*text) = result; 
    148155    else 
    149156        (*text)--; 
     157 
     158    /* Additional check to ensure no buffer underruns. */ 
     159    if (*text && *text < begin) 
     160        *text = NULL; 
    150161} 
    151162 
    152163/* --------------------------------------------------------------------------------------------- */ 
    str_utf8_cprev_noncomb_char (const char **text, const char *begin) 
    262273 
    263274    while ((*text) != begin) 
    264275    { 
    265         str_utf8_cprev_char_safe (text); 
     276        str_utf8_cprev_char_safe (text, begin); 
    266277        count++; 
    267278        if (!str_utf8_iscombiningmark (*text)) 
    268279            break; 
    str_utf8_trunc (const char *text, int width) 
    889900} 
    890901 
    891902/* --------------------------------------------------------------------------------------------- */ 
     903/* Converts a character index into a byte offset. */ 
    892904 
    893905static int 
    894906str_utf8_offset_to_pos (const char *text, size_t length) 
    895907{ 
     908    glong size; 
     909 
    896910    if (str_utf8_is_valid_string (text)) 
     911    { 
     912        /* Limit index by string size. */ 
     913        size = g_utf8_strlen (text, -1); 
     914        if (size < (glong) length) 
     915            length = (size_t) size; 
    897916        return g_utf8_offset_to_pointer (text, length) - text; 
     917    } 
    898918    else 
    899919    { 
    900920        int result; 
    str_utf8_offset_to_pos (const char *text, size_t length) 
    902922 
    903923        buffer = g_string_new (text); 
    904924        str_utf8_fix_string (buffer->str); 
     925        /* Limit index by string size. */ 
     926        size = g_utf8_strlen (buffer->str, -1); 
     927        if (size < (glong) length) 
     928            length = (size_t) size; 
    905929        result = g_utf8_offset_to_pointer (buffer->str, length) - buffer->str; 
    906930        g_string_free (buffer, TRUE); 
    907931        return result; 
  • lib/widget/input.c

    diff --git a/lib/widget/input.c b/lib/widget/input.c
    index 625b394a9..d42623741 100644
    a b backward_word (WInput * in) 
    425425{ 
    426426    const char *p; 
    427427 
     428    /* p is limited by strlen. */ 
    428429    p = in->buffer + str_offset_to_pos (in->buffer, in->point); 
    429430 
    430     while (p != in->buffer) 
     431    while (p && p != in->buffer) 
    431432    { 
    432433        const char *p_tmp; 
    433434 
    434435        p_tmp = p; 
    435         str_cprev_char (&p); 
    436         if (!str_isspace (p) && !str_ispunct (p)) 
     436        str_cprev_char (&p, in->buffer); 
     437        if (p) 
    437438        { 
    438             p = p_tmp; 
    439             break; 
     439            /* 
     440             * If preceding char isn't a word boundary (↔ we're ·in· a word), then undo last move and 
     441             * break from loop. 
     442             */ 
     443 
     444            if (!str_isspace (p) && !str_ispunct (p)) 
     445            { 
     446                p = p_tmp; 
     447                break; 
     448            } 
     449            in->point--; 
    440450        } 
    441         in->point--; 
    442451    } 
    443     while (p != in->buffer) 
     452 
     453    /* Further skip the ·word· chars, if not outside the string. */ 
     454    while (p && p != in->buffer) 
    444455    { 
    445         str_cprev_char (&p); 
    446         if (str_isspace (p) || str_ispunct (p)) 
     456        str_cprev_char (&p, in->buffer); 
     457        /* Stop when a word boundary char is detected or when the string ends. */ 
     458        if (!p || str_isspace (p) || str_ispunct (p)) 
    447459            break; 
    448460 
    449461        in->point--; 
  • lib/widget/input_complete.c

    diff --git a/lib/widget/input_complete.c b/lib/widget/input_complete.c
    index 59a994d62..22aeb2312 100644
    a b try_complete_commands_prepare (try_complete_automation_state_t * state, char *te 
    843843        ti = text; 
    844844    else 
    845845    { 
    846         ti = str_get_prev_char (&text[*lc_start]); 
     846        ti = str_get_prev_char (&text[*lc_start], text); 
    847847        while (ti > text && whitespace (ti[0])) 
    848             str_prev_char (&ti); 
     848            str_prev_char (&ti, text); 
    849849    } 
    850850 
    851     if (ti == text) 
    852         state->in_command_position++; 
    853     else if (strchr (command_separator_chars, ti[0]) != NULL) 
     851    if (!ti) 
    854852    { 
    855853        state->in_command_position++; 
    856         if (ti != text) 
    857         { 
    858             int this_char, prev_char; 
     854        ti = text; 
     855    } 
    859856 
    860             /* Handle the two character tokens '>&', '<&', and '>|'. 
    861                We are not in a command position after one of these. */ 
    862             this_char = ti[0]; 
    863             prev_char = str_get_prev_char (ti)[0]; 
     857    /* Is there any more preceding text, and there's a command separator? */ 
     858    if (ti != text && strchr (command_separator_chars, ti[0]) != NULL) 
     859    { 
     860        int this_char, prev_char = '\0'; 
     861        char *prev_char_p; 
    864862 
    865             /* Quoted */ 
    866             if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) 
    867                 || (this_char == '|' && prev_char == '>') || (ti != text 
    868                                                               && str_get_prev_char (ti)[0] == '\\')) 
    869                 state->in_command_position = 0; 
    870         } 
     863        /* Initial assumption that we're at command. */ 
     864        state->in_command_position++; 
     865 
     866        /* Handle the two character tokens '>&', '<&', and '>|'. 
     867           We are not in a command position after one of these. */ 
     868        this_char = ti[0]; 
     869        prev_char_p = str_get_prev_char (ti, text); 
     870        if (prev_char_p) 
     871            prev_char = prev_char_p[0]; 
     872 
     873        if ((this_char == '&' && (strchr ("<>", prev_char))) 
     874            || (this_char == '|' && prev_char == '>') || prev_char == '\\') 
     875            state->in_command_position = 0; 
    871876    } 
    872877} 
    873878 
    complete_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void 
    10431048            /* Refill the list box and start again */ 
    10441049            else if (end == min_end) 
    10451050            { 
    1046                 end = str_get_prev_char (&input->buffer[end]) - input->buffer; 
     1051                end = str_get_prev_char (&input->buffer[end], input->buffer) - input->buffer; 
     1052                if (end < 0) 
     1053                    end = 0; 
    10471054                input_handle_char (input, parm); 
    10481055                h->ret_value = B_USER; 
    10491056                dlg_stop (h); 
    complete_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void 
    10541061                int i; 
    10551062                GList *e; 
    10561063 
    1057                 new_end = str_get_prev_char (&input->buffer[end]) - input->buffer; 
     1064                new_end = str_get_prev_char (&input->buffer[end], input->buffer) - input->buffer; 
     1065                /* The buffer is empty (no previous char available)? */ 
     1066                if (new_end < 0) 
     1067                    new_end = 0; 
    10581068 
    10591069                for (i = 0, e = listbox_get_first_link (LISTBOX (g->current->data)); 
    10601070                     e != NULL; i++, e = g_list_next (e)) 
    complete_engine_fill_completions (WInput * in) 
    14011411{ 
    14021412    char *s; 
    14031413    const char *word_separators; 
     1414    gboolean separator_found = FALSE; 
    14041415 
    14051416    word_separators = (in->completion_flags & INPUT_COMPLETE_SHELL_ESC) ? " \t;|<>" : "\t;|<>"; 
    14061417 
    complete_engine_fill_completions (WInput * in) 
    14161427            str_next_char (&s); 
    14171428    } 
    14181429 
    1419     for (; s >= in->buffer; str_prev_char (&s)) 
     1430    for (; s; str_prev_char (&s, in->buffer)) 
    14201431    { 
    14211432        start = s - in->buffer; 
    14221433        if (strchr (word_separators, *s) != NULL && !strutils_is_char_escaped (in->buffer, s)) 
     1434        { 
     1435            separator_found = TRUE; 
    14231436            break; 
     1437        } 
    14241438    } 
    14251439 
     1440    /* Note: str_prev_char() returns NULL if no preceding character fitting within string found. */ 
     1441    if (s < in->buffer) 
     1442        s = in->buffer; 
     1443 
    14261444    if (start < end) 
    14271445    { 
    1428         str_next_char (&s); 
     1446        if (separator_found) 
     1447            str_next_char (&s); 
     1448        if (s > in->buffer + end) 
     1449            s = in->buffer + end; 
    14291450        start = s - in->buffer; 
    14301451    } 
    14311452 
  • src/help.c

    diff --git a/src/help.c b/src/help.c
    index f5922f086..2c437ea57 100644
    a b move_backward2 (const char *c, int lines) 
    229229    int line; 
    230230 
    231231    currentpoint = c; 
    232     for (line = 0, p = currentpoint; (*p != '\0') && ((int) (p - fdata) >= 0); str_cprev_char (&p)) 
     232    for (line = 0, p = currentpoint; p && (*p != '\0') && ((int) (p - fdata) >= 0); 
     233         str_cprev_char (&p, fdata)) 
    233234    { 
    234235        if (*p == CHAR_NODE_END) 
    235236        { 
  • src/usermenu.c

    diff --git a/src/usermenu.c b/src/usermenu.c
    index 698244220..695a56814 100644
    a b check_patterns (char *p) 
    133133   point after argument. */ 
    134134 
    135135static char * 
    136 extract_arg (char *p, char *arg, int size) 
     136extract_arg (char *p, char *arg, const char *begin, int size) 
    137137{ 
    138138    while (*p != '\0' && whiteness (*p)) 
    139139        p++; 
    extract_arg (char *p, char *arg, int size) 
    152152        p = np; 
    153153    } 
    154154    *arg = '\0'; 
    155     if (*p == '\0' || *p == '\n') 
    156         str_prev_char (&p); 
     155    if (p && (*p == '\0' || *p == '\n')) 
     156        str_prev_char (&p, begin); 
     157    if (!p) 
     158        p = (char *) begin; 
    157159    return p; 
    158160} 
    159161 
    test_type (WPanel * panel, char *arg) 
    215217   p. Returns the point after condition. */ 
    216218 
    217219static char * 
    218 test_condition (const WEdit * edit_widget, char *p, gboolean * condition) 
     220test_condition (const WEdit * edit_widget, char *p, const char *begin, gboolean * condition) 
    219221{ 
    220222    char arg[256]; 
    221223    const mc_search_type_t search_type = easy_patterns ? MC_SEARCH_T_GLOB : MC_SEARCH_T_REGEX; 
    222224 
    223225    /* Handle one condition */ 
    224     for (; *p != '\n' && *p != '&' && *p != '|'; p++) 
     226    for (; p && *p != '\n' && *p != '&' && *p != '|'; p++) 
    225227    { 
    226228        WPanel *panel = NULL; 
    227229 
    test_condition (const WEdit * edit_widget, char *p, gboolean * condition) 
    238240        switch (*p++) 
    239241        { 
    240242        case '!': 
    241             p = test_condition (edit_widget, p, condition); 
     243            p = test_condition (edit_widget, p, begin, condition); 
    242244            *condition = !*condition; 
    243             str_prev_char (&p); 
     245            str_prev_char (&p, begin); 
    244246            break; 
    245247        case 'f':              /* file name pattern */ 
    246             p = extract_arg (p, arg, sizeof (arg)); 
     248            p = extract_arg (p, arg, begin, sizeof (arg)); 
    247249#ifdef USE_INTERNAL_EDIT 
    248250            if (edit_widget != NULL) 
    249251            { 
    test_condition (const WEdit * edit_widget, char *p, gboolean * condition) 
    267269                syntax_type = edit_get_syntax_type (edit_widget); 
    268270                if (syntax_type != NULL) 
    269271                { 
    270                     p = extract_arg (p, arg, sizeof (arg)); 
     272                    p = extract_arg (p, arg, begin, sizeof (arg)); 
    271273                    *condition = mc_search (arg, DEFAULT_CHARSET, syntax_type, MC_SEARCH_T_NORMAL); 
    272274                } 
    273275            } 
    274276#endif 
    275277            break; 
    276278        case 'd': 
    277             p = extract_arg (p, arg, sizeof (arg)); 
     279            p = extract_arg (p, arg, begin, sizeof (arg)); 
    278280            *condition = panel != NULL 
    279281                && mc_search (arg, DEFAULT_CHARSET, vfs_path_as_str (panel->cwd_vpath), 
    280282                              search_type); 
    281283            break; 
    282284        case 't': 
    283             p = extract_arg (p, arg, sizeof (arg)); 
     285            p = extract_arg (p, arg, begin, sizeof (arg)); 
    284286            *condition = panel != NULL && test_type (panel, arg); 
    285287            break; 
    286288        case 'x':              /* executable */ 
    287289            { 
    288290                struct stat status; 
    289291 
    290                 p = extract_arg (p, arg, sizeof (arg)); 
     292                p = extract_arg (p, arg, begin, sizeof (arg)); 
    291293                *condition = stat (arg, &status) == 0 && is_exe (status.st_mode); 
    292294                break; 
    293295            } 
    debug_out (char *start, char *end, gboolean condition) 
    356358   the point just before the end of line. */ 
    357359 
    358360static char * 
    359 test_line (const WEdit * edit_widget, char *p, gboolean * result) 
     361test_line (const WEdit * edit_widget, char *p, const char *begin, gboolean * result) 
    360362{ 
    361363    char operator; 
    362364 
    363365    /* Repeat till end of line */ 
    364     while (*p != '\0' && *p != '\n') 
     366    while (p && *p != '\0' && *p != '\n') 
    365367    { 
    366368        char *debug_start, *debug_end; 
    367369        gboolean condition = TRUE; 
    test_line (const WEdit * edit_widget, char *p, gboolean * result) 
    384386            break; 
    385387 
    386388        debug_start = p; 
    387         p = test_condition (edit_widget, p, &condition); 
     389        p = test_condition (edit_widget, p, begin, &condition); 
    388390        debug_end = p; 
    389391        /* Add one debug statement */ 
    390392        debug_out (debug_start, debug_end, condition); 
    test_line (const WEdit * edit_widget, char *p, gboolean * result) 
    413415    /* Report debug message */ 
    414416    debug_out (NULL, NULL, TRUE); 
    415417 
    416     if (*p == '\0' || *p == '\n') 
    417         str_prev_char (&p); 
     418    if (p && (*p == '\0' || *p == '\n')) 
     419        str_prev_char (&p, begin); 
     420    if (!p) 
     421        p = (char *) begin; 
    418422    return p; 
    419423} 
    420424 
    user_menu_cmd (const WEdit * edit_widget, const char *menu_file, int selected_en 
    10371041                if (*(p + 1) == '=') 
    10381042                { 
    10391043                    /* Combined adding and default */ 
    1040                     p = test_line (edit_widget, p + 1, &accept_entry); 
     1044                    p = test_line (edit_widget, p + 1, data, &accept_entry); 
    10411045                    if (selected == 0 && accept_entry) 
    10421046                        selected = menu_lines; 
    10431047                } 
    10441048                else 
    10451049                { 
    10461050                    /* A condition for adding the entry */ 
    1047                     p = test_line (edit_widget, p, &accept_entry); 
     1051                    p = test_line (edit_widget, p, data, &accept_entry); 
    10481052                } 
    10491053                break; 
    10501054 
    user_menu_cmd (const WEdit * edit_widget, const char *menu_file, int selected_en 
    10521056                if (*(p + 1) == '+') 
    10531057                { 
    10541058                    /* Combined adding and default */ 
    1055                     p = test_line (edit_widget, p + 1, &accept_entry); 
     1059                    p = test_line (edit_widget, p + 1, data, &accept_entry); 
    10561060                    if (selected == 0 && accept_entry) 
    10571061                        selected = menu_lines; 
    10581062                } 
    user_menu_cmd (const WEdit * edit_widget, const char *menu_file, int selected_en 
    10601064                { 
    10611065                    /* A condition for making the entry default */ 
    10621066                    i = 1; 
    1063                     p = test_line (edit_widget, p, &i); 
     1067                    p = test_line (edit_widget, p, data, &i); 
    10641068                    if (selected == 0 && i != 0) 
    10651069                        selected = menu_lines; 
    10661070                }