Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit131825c

Browse files
committed
Code review for psql's helpSQL() function.
The loops to identify word boundaries could access past the end ofthe input string. Likely that would never result in an actualcrash, but it makes valgrind unhappy.The logic to try different numbers of words didn't work when theinput has two words but we only have a match to the first, eg"\h with select". (We must "continue" the pass loop, not "break".)The logic to compute nl_count was bizarrely managed, and in atleast two code paths could end up calling PageOutput withnl_count = 0, resulting in failing to paginate output that shouldhave been fed to the pager. Also, in v12 and up, the nl_countcalculation hadn't been updated to account for the addition of a URL.The PQExpBuffer holding the command syntax details wasn't freed,resulting in a session-lifespan memory leak.While here, improve some comments, choose a more descriptive namefor a variable, fix inconsistent datatype choice for another variable.Per bug #16837 from Alexander Lakhin. This code is very old,so back-patch to all supported branches.Kyotaro Horiguchi and Tom LaneDiscussion:https://postgr.es/m/16837-479bcd56040c71b3@postgresql.org
1 parent41309f7 commit131825c

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

‎src/bin/psql/help.c

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ helpSQL(const char *topic, unsigned short int pager)
423423
inti;
424424
intj;
425425

426+
/* Find screen width to determine how many columns will fit */
426427
#ifdefTIOCGWINSZ
427428
structwinsizescreen_size;
428429

@@ -460,56 +461,63 @@ helpSQL(const char *topic, unsigned short int pager)
460461
else
461462
{
462463
inti,
463-
j,
464-
x=0;
465-
boolhelp_found= false;
464+
pass;
466465
FILE*output=NULL;
467466
size_tlen,
468-
wordlen;
469-
intnl_count=0;
467+
wordlen,
468+
j;
469+
intnl_count;
470470

471471
/*
472+
* len is the amount of the input to compare to the help topic names.
472473
* We first try exact match, then first + second words, then first
473474
* word only.
474475
*/
475476
len=strlen(topic);
476477

477-
for (x=1;x <=3;x++)
478+
for (pass=1;pass <=3;pass++)
478479
{
479-
if (x>1)/* Nothing on first pass - try the opening
480+
if (pass>1)/* Nothing on first pass - try the opening
480481
* word(s) */
481482
{
482483
wordlen=j=1;
483-
while (topic[j]!=' '&&j++<len)
484+
while (j<len&&topic[j++]!=' ')
484485
wordlen++;
485-
if (x==2)
486+
if (pass==2&&j<len)
486487
{
487-
j++;
488-
while (topic[j]!=' '&&j++ <=len)
488+
wordlen++;
489+
while (j<len&&topic[j++]!=' ')
489490
wordlen++;
490491
}
491-
if (wordlen >=len)/* Don't try again if the same word */
492+
if (wordlen >=len)
492493
{
493-
if (!output)
494-
output=PageOutput(nl_count,pager ?&(pset.popt.topt) :NULL);
495-
break;
494+
/* Failed to shorten input, so try next pass if any */
495+
continue;
496496
}
497497
len=wordlen;
498498
}
499499

500-
/* Count newlines for pager */
500+
/*
501+
* Count newlines for pager. This logic must agree with what the
502+
* following loop will do!
503+
*/
504+
nl_count=0;
501505
for (i=0;QL_HELP[i].cmd;i++)
502506
{
503507
if (pg_strncasecmp(topic,QL_HELP[i].cmd,len)==0||
504508
strcmp(topic,"*")==0)
505509
{
510+
/* magic constant here must match format below! */
506511
nl_count+=5+QL_HELP[i].nl_count;
507512

508513
/* If we have an exact match, exit. Fixes \h SELECT */
509514
if (pg_strcasecmp(topic,QL_HELP[i].cmd)==0)
510515
break;
511516
}
512517
}
518+
/* If no matches, don't open the output yet */
519+
if (nl_count==0)
520+
continue;
513521

514522
if (!output)
515523
output=PageOutput(nl_count,pager ?&(pset.popt.topt) :NULL);
@@ -523,24 +531,31 @@ helpSQL(const char *topic, unsigned short int pager)
523531

524532
initPQExpBuffer(&buffer);
525533
QL_HELP[i].syntaxfunc(&buffer);
526-
help_found= true;
534+
/* # of newlines in format must match constant above! */
527535
fprintf(output,_("Command: %s\n"
528536
"Description: %s\n"
529537
"Syntax:\n%s\n\n"),
530538
QL_HELP[i].cmd,
531539
_(QL_HELP[i].help),
532540
buffer.data);
541+
termPQExpBuffer(&buffer);
542+
533543
/* If we have an exact match, exit. Fixes \h SELECT */
534544
if (pg_strcasecmp(topic,QL_HELP[i].cmd)==0)
535545
break;
536546
}
537547
}
538-
if (help_found)/* Don't keep trying if we got a match */
539-
break;
548+
break;
540549
}
541550

542-
if (!help_found)
543-
fprintf(output,_("No help available for \"%s\".\nTry \\h with no arguments to see available help.\n"),topic);
551+
/* If we never found anything, report that */
552+
if (!output)
553+
{
554+
output=PageOutput(2,pager ?&(pset.popt.topt) :NULL);
555+
fprintf(output,_("No help available for \"%s\".\n"
556+
"Try \\h with no arguments to see available help.\n"),
557+
topic);
558+
}
544559

545560
ClosePager(output);
546561
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp