mirror of
git://git.sv.gnu.org/nano.git
synced 2024-12-26 04:16:55 +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 -
|
||||
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
|
||||
- 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 replaceall = 0, numreplaced = -1;
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
int dollarreplace = 0;
|
||||
/* Whether we're doing a forward regex replace of "$". */
|
||||
#endif
|
||||
filestruct *fileptr = NULL;
|
||||
char *copy;
|
||||
|
||||
switch (*i) {
|
||||
case -1: /* Aborted enter */
|
||||
case -1: /* Aborted enter. */
|
||||
if (last_replace[0] != '\0')
|
||||
answer = mallocstrcpy(answer, last_replace);
|
||||
statusbar(_("Replace Cancelled"));
|
||||
replace_abort();
|
||||
return 0;
|
||||
case 0: /* They actually entered something */
|
||||
case 0: /* They actually entered something. */
|
||||
break;
|
||||
default:
|
||||
if (*i != -2) { /* First page, last page, for example, could
|
||||
get here */
|
||||
* get here. */
|
||||
do_early_abort();
|
||||
replace_abort();
|
||||
return 0;
|
||||
@ -634,7 +637,7 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
||||
while (1) {
|
||||
size_t match_len;
|
||||
|
||||
/* Sweet optimization by Rocco here */
|
||||
/* Sweet optimization by Rocco here. */
|
||||
fileptr = findnextstr(fileptr || replaceall || search_last_line,
|
||||
FALSE, begin, *beginx, prevanswer);
|
||||
|
||||
@ -646,11 +649,11 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
||||
if (fileptr == NULL)
|
||||
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))
|
||||
continue;
|
||||
|
||||
/* If we're here, we've found the search string */
|
||||
/* If we're here, we've found the search string. */
|
||||
if (numreplaced == -1)
|
||||
numreplaced = 0;
|
||||
|
||||
@ -695,9 +698,18 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
||||
length_change = strlen(copy) - strlen(current->data);
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
if (ISSET(USE_REGEXP))
|
||||
if (ISSET(USE_REGEXP)) {
|
||||
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
|
||||
match_len = strlen(prevanswer);
|
||||
|
||||
@ -725,7 +737,7 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
||||
#endif
|
||||
current_x += match_len + length_change - 1;
|
||||
|
||||
/* Cleanup */
|
||||
/* Cleanup. */
|
||||
totsize += length_change;
|
||||
free(current->data);
|
||||
current->data = copy;
|
||||
@ -733,8 +745,28 @@ int do_replace_loop(const char *prevanswer, const filestruct *begin,
|
||||
edit_refresh();
|
||||
set_modified();
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user