mirror of
git://git.sv.gnu.org/nano.git
synced 2024-12-27 12:49:45 +03:00
avoid infinite loop when doing a forward regex replace of "$"
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1580 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
This commit is contained in:
parent
b78649b664
commit
b7cb6a38c8
@ -1,4 +1,8 @@
|
|||||||
CVS code -
|
CVS code -
|
||||||
|
search.c:
|
||||||
|
do_replace_loop()
|
||||||
|
- Fix potential infinite loop when doing a forward regex replace
|
||||||
|
of "$". (DLR; found by Mike Frysinger)
|
||||||
|
|
||||||
GNU nano 1.3.0 - 2003.10.22
|
GNU nano 1.3.0 - 2003.10.22
|
||||||
- General:
|
- General:
|
||||||
|
56
src/search.c
56
src/search.c
@ -608,22 +608,25 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
|||||||
int *beginx, int wholewords, int *i)
|
int *beginx, int wholewords, int *i)
|
||||||
{
|
{
|
||||||
int replaceall = 0, numreplaced = -1;
|
int replaceall = 0, numreplaced = -1;
|
||||||
|
#ifdef HAVE_REGEX_H
|
||||||
|
int dollarreplace = 0;
|
||||||
|
/* Whether we're doing a forward regex replace of "$". */
|
||||||
|
#endif
|
||||||
filestruct *fileptr = NULL;
|
filestruct *fileptr = NULL;
|
||||||
char *copy;
|
char *copy;
|
||||||
|
|
||||||
switch (*i) {
|
switch (*i) {
|
||||||
case -1: /* Aborted enter */
|
case -1: /* Aborted enter. */
|
||||||
if (last_replace[0] != '\0')
|
if (last_replace[0] != '\0')
|
||||||
answer = mallocstrcpy(answer, last_replace);
|
answer = mallocstrcpy(answer, last_replace);
|
||||||
statusbar(_("Replace Cancelled"));
|
statusbar(_("Replace Cancelled"));
|
||||||
replace_abort();
|
replace_abort();
|
||||||
return 0;
|
return 0;
|
||||||
case 0: /* They actually entered something */
|
case 0: /* They actually entered something. */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (*i != -2) { /* First page, last page, for example, could
|
if (*i != -2) { /* First page, last page, for example, could
|
||||||
get here */
|
* get here. */
|
||||||
do_early_abort();
|
do_early_abort();
|
||||||
replace_abort();
|
replace_abort();
|
||||||
return 0;
|
return 0;
|
||||||
@ -634,7 +637,7 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
|||||||
while (1) {
|
while (1) {
|
||||||
size_t match_len;
|
size_t match_len;
|
||||||
|
|
||||||
/* Sweet optimization by Rocco here */
|
/* Sweet optimization by Rocco here. */
|
||||||
fileptr = findnextstr(fileptr || replaceall || search_last_line,
|
fileptr = findnextstr(fileptr || replaceall || search_last_line,
|
||||||
FALSE, begin, *beginx, prevanswer);
|
FALSE, begin, *beginx, prevanswer);
|
||||||
|
|
||||||
@ -646,11 +649,11 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
|||||||
if (fileptr == NULL)
|
if (fileptr == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Make sure only whole words are found */
|
/* Make sure only whole words are found. */
|
||||||
if (wholewords && !is_whole_word(current_x, fileptr->data, prevanswer))
|
if (wholewords && !is_whole_word(current_x, fileptr->data, prevanswer))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If we're here, we've found the search string */
|
/* If we're here, we've found the search string. */
|
||||||
if (numreplaced == -1)
|
if (numreplaced == -1)
|
||||||
numreplaced = 0;
|
numreplaced = 0;
|
||||||
|
|
||||||
@ -695,9 +698,18 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
|||||||
length_change = strlen(copy) - strlen(current->data);
|
length_change = strlen(copy) - strlen(current->data);
|
||||||
|
|
||||||
#ifdef HAVE_REGEX_H
|
#ifdef HAVE_REGEX_H
|
||||||
if (ISSET(USE_REGEXP))
|
if (ISSET(USE_REGEXP)) {
|
||||||
match_len = regmatches[0].rm_eo - regmatches[0].rm_so;
|
match_len = regmatches[0].rm_eo - regmatches[0].rm_so;
|
||||||
else
|
/* If we're on the line we started the replace on, the
|
||||||
|
* match length is 0, and current_x is at the end of the
|
||||||
|
* the line, we're doing a forward regex replace of "$".
|
||||||
|
* We have to handle this as a special case so that we
|
||||||
|
* don't end up infinitely tacking the replace string
|
||||||
|
* onto the end of the line. */
|
||||||
|
if (current == begin && match_len == 0 && current_x ==
|
||||||
|
strlen(current->data))
|
||||||
|
dollarreplace = 1;
|
||||||
|
} else
|
||||||
#endif
|
#endif
|
||||||
match_len = strlen(prevanswer);
|
match_len = strlen(prevanswer);
|
||||||
|
|
||||||
@ -725,7 +737,7 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
|||||||
#endif
|
#endif
|
||||||
current_x += match_len + length_change - 1;
|
current_x += match_len + length_change - 1;
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup. */
|
||||||
totsize += length_change;
|
totsize += length_change;
|
||||||
free(current->data);
|
free(current->data);
|
||||||
current->data = copy;
|
current->data = copy;
|
||||||
@ -733,8 +745,28 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
|||||||
edit_refresh();
|
edit_refresh();
|
||||||
set_modified();
|
set_modified();
|
||||||
numreplaced++;
|
numreplaced++;
|
||||||
} else if (*i == -1) /* Abort, else do nothing and continue
|
|
||||||
loop */
|
#ifdef HAVE_REGEX_H
|
||||||
|
if (dollarreplace == 1) {
|
||||||
|
/* If we're here, we're doing a forward regex replace of
|
||||||
|
* "$", and the replacement's just been made. Avoid
|
||||||
|
* infinite replacement by manually moving the search to
|
||||||
|
* the next line, wrapping to the first line if we're on
|
||||||
|
* the last line of the file. Afterwards, if we're back
|
||||||
|
* on the line where we started, manually break out of
|
||||||
|
* the loop. */
|
||||||
|
current_x = 0;
|
||||||
|
if (current->next != NULL)
|
||||||
|
current = current->next;
|
||||||
|
else
|
||||||
|
current = fileage;
|
||||||
|
if (current == begin)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else if (*i == -1) /* Break out of the loop, else do
|
||||||
|
* nothing and continue loop. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user