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

Commit64bdb6e

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 parent366d302 commit64bdb6e

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
@@ -534,6 +534,7 @@ helpSQL(const char *topic, unsigned short int pager)
534534
inti;
535535
intj;
536536

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

@@ -571,56 +572,63 @@ helpSQL(const char *topic, unsigned short int pager)
571572
else
572573
{
573574
inti,
574-
j,
575-
x=0;
576-
boolhelp_found= false;
575+
pass;
577576
FILE*output=NULL;
578577
size_tlen,
579-
wordlen;
580-
intnl_count=0;
578+
wordlen,
579+
j;
580+
intnl_count;
581581

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

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

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

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

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

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

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

663678
ClosePager(output);
664679
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp