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

Commitf76a850

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 parent7b4c660 commitf76a850

File tree

1 file changed

+37
-22
lines changed

1 file changed

+37
-22
lines changed

‎src/bin/psql/help.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ helpSQL(const char *topic, unsigned short int pager)
535535
inti;
536536
intj;
537537

538+
/* Find screen width to determine how many columns will fit */
538539
#ifdefTIOCGWINSZ
539540
structwinsizescreen_size;
540541

@@ -572,56 +573,63 @@ helpSQL(const char *topic, unsigned short int pager)
572573
else
573574
{
574575
inti,
575-
j,
576-
x=0;
577-
boolhelp_found= false;
576+
pass;
578577
FILE*output=NULL;
579578
size_tlen,
580-
wordlen;
581-
intnl_count=0;
579+
wordlen,
580+
j;
581+
intnl_count;
582582

583583
/*
584+
* len is the amount of the input to compare to the help topic names.
584585
* We first try exact match, then first + second words, then first
585586
* word only.
586587
*/
587588
len=strlen(topic);
588589

589-
for (x=1;x <=3;x++)
590+
for (pass=1;pass <=3;pass++)
590591
{
591-
if (x>1)/* Nothing on first pass - try the opening
592+
if (pass>1)/* Nothing on first pass - try the opening
592593
* word(s) */
593594
{
594595
wordlen=j=1;
595-
while (topic[j]!=' '&&j++<len)
596+
while (j<len&&topic[j++]!=' ')
596597
wordlen++;
597-
if (x==2)
598+
if (pass==2&&j<len)
598599
{
599-
j++;
600-
while (topic[j]!=' '&&j++ <=len)
600+
wordlen++;
601+
while (j<len&&topic[j++]!=' ')
601602
wordlen++;
602603
}
603-
if (wordlen >=len)/* Don't try again if the same word */
604+
if (wordlen >=len)
604605
{
605-
if (!output)
606-
output=PageOutput(nl_count,pager ?&(pset.popt.topt) :NULL);
607-
break;
606+
/* Failed to shorten input, so try next pass if any */
607+
continue;
608608
}
609609
len=wordlen;
610610
}
611611

612-
/* Count newlines for pager */
612+
/*
613+
* Count newlines for pager. This logic must agree with what the
614+
* following loop will do!
615+
*/
616+
nl_count=0;
613617
for (i=0;QL_HELP[i].cmd;i++)
614618
{
615619
if (pg_strncasecmp(topic,QL_HELP[i].cmd,len)==0||
616620
strcmp(topic,"*")==0)
617621
{
618-
nl_count+=5+QL_HELP[i].nl_count;
622+
/* magic constant here must match format below! */
623+
nl_count+=7+QL_HELP[i].nl_count;
619624

620625
/* If we have an exact match, exit. Fixes \h SELECT */
621626
if (pg_strcasecmp(topic,QL_HELP[i].cmd)==0)
622627
break;
623628
}
624629
}
630+
/* If no matches, don't open the output yet */
631+
if (nl_count==0)
632+
continue;
625633

626634
if (!output)
627635
output=PageOutput(nl_count,pager ?&(pset.popt.topt) :NULL);
@@ -636,10 +644,10 @@ helpSQL(const char *topic, unsigned short int pager)
636644

637645
initPQExpBuffer(&buffer);
638646
QL_HELP[i].syntaxfunc(&buffer);
639-
help_found= true;
640647
url=psprintf("https://www.postgresql.org/docs/%s/%s.html",
641648
strstr(PG_VERSION,"devel") ?"devel" :PG_MAJORVERSION,
642649
QL_HELP[i].docbook_id);
650+
/* # of newlines in format must match constant above! */
643651
fprintf(output,_("Command: %s\n"
644652
"Description: %s\n"
645653
"Syntax:\n%s\n\n"
@@ -649,17 +657,24 @@ helpSQL(const char *topic, unsigned short int pager)
649657
buffer.data,
650658
url);
651659
free(url);
660+
termPQExpBuffer(&buffer);
661+
652662
/* If we have an exact match, exit. Fixes \h SELECT */
653663
if (pg_strcasecmp(topic,QL_HELP[i].cmd)==0)
654664
break;
655665
}
656666
}
657-
if (help_found)/* Don't keep trying if we got a match */
658-
break;
667+
break;
659668
}
660669

661-
if (!help_found)
662-
fprintf(output,_("No help available for \"%s\".\nTry \\h with no arguments to see available help.\n"),topic);
670+
/* If we never found anything, report that */
671+
if (!output)
672+
{
673+
output=PageOutput(2,pager ?&(pset.popt.topt) :NULL);
674+
fprintf(output,_("No help available for \"%s\".\n"
675+
"Try \\h with no arguments to see available help.\n"),
676+
topic);
677+
}
663678

664679
ClosePager(output);
665680
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp