5050#define atoxid (x ) ((TransactionId) strtoul((x), NULL, 10))
5151
5252#define MAX_TOKEN 256
53+ #define MAX_LINE 8192
5354
5455/* callback data for check_network_callback */
5556typedef struct check_network_data
@@ -93,7 +94,7 @@ static MemoryContext parsed_ident_context = NULL;
9394
9495
9596static MemoryContext tokenize_file (const char * filename , FILE * file ,
96- List * * lines , List * * line_nums );
97+ List * * lines , List * * line_nums , List * * raw_lines );
9798static List * tokenize_inc_file (List * tokens , const char * outer_filename ,
9899 const char * inc_filename );
99100static bool parse_hba_auth_opt (char * name , char * val , HbaLine * hbaline ,
@@ -111,7 +112,8 @@ pg_isblank(const char c)
111112
112113
113114/*
114- * Grab one token out of fp. Tokens are strings of non-blank
115+ * Grab one token out of the string pointed to by lineptr.
116+ * Tokens are strings of non-blank
115117 * characters bounded by blank characters, commas, beginning of line, and
116118 * end of line. Blank means space or tab. Tokens can be delimited by
117119 * double quotes (this allows the inclusion of blanks, but not newlines).
@@ -134,7 +136,7 @@ pg_isblank(const char c)
134136 * Handle comments.
135137 */
136138static bool
137- next_token (FILE * fp , char * buf , int bufsz , bool * initial_quote ,
139+ next_token (char * * lineptr , char * buf , int bufsz , bool * initial_quote ,
138140 bool * terminating_comma )
139141{
140142 int c ;
@@ -151,10 +153,10 @@ next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote,
151153 * terminating_comma = false;
152154
153155 /* Move over initial whitespace and commas */
154- while ((c = getc ( fp )) != EOF && (pg_isblank (c ) || c == ',' ))
156+ while ((c = ( * ( * lineptr ) ++ )) != '\0' && (pg_isblank (c ) || c == ',' ))
155157 ;
156158
157- if (c == EOF || c == '\n' )
159+ if (c == '\0' || c == '\n' )
158160 {
159161 * buf = '\0' ;
160162 return false;
@@ -164,17 +166,17 @@ next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote,
164166 * Build a token in buf of next characters up to EOF, EOL, unquoted comma,
165167 * or unquoted whitespace.
166168 */
167- while (c != EOF && c != '\n' &&
169+ while (c != '\0' && c != '\n' &&
168170 (!pg_isblank (c ) || in_quote ))
169171 {
170172 /* skip comments to EOL */
171173 if (c == '#' && !in_quote )
172174 {
173- while ((c = getc ( fp )) != EOF && c != '\n' )
175+ while ((c = ( * ( * lineptr ) ++ )) != '\0' && c != '\n' )
174176 ;
175177 /* If only comment, consume EOL too; return EOL */
176- if (c != EOF && buf == start_buf )
177- c = getc ( fp ) ;
178+ if (c != '\0' && buf == start_buf )
179+ ( * lineptr ) ++ ;
178180 break ;
179181 }
180182
@@ -186,7 +188,7 @@ next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote,
186188 errmsg ("authentication file token too long, skipping: \"%s\"" ,
187189 start_buf )));
188190 /* Discard remainder of line */
189- while ((c = getc ( fp )) != EOF && c != '\n' )
191+ while ((c = ( * ( * lineptr ) ++ )) != '\0' && c != '\n' )
190192 ;
191193 break ;
192194 }
@@ -215,15 +217,14 @@ next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote,
215217 * initial_quote = true;
216218 }
217219
218- c = getc ( fp ) ;
220+ c = * ( * lineptr ) ++ ;
219221 }
220222
221223 /*
222224 * Put back the char right after the token (critical in case it is EOL,
223225 * since we need to detect end-of-line at next call).
224226 */
225- if (c != EOF )
226- ungetc (c , fp );
227+ (* lineptr )-- ;
227228
228229 * buf = '\0' ;
229230
@@ -258,13 +259,13 @@ copy_hba_token(HbaToken *in)
258259
259260
260261/*
261- * Tokenize one HBA field from a file , handling file inclusion and comma lists.
262+ * Tokenize one HBA field from a line , handling file inclusion and comma lists.
262263 *
263264 * The result is a List of HbaToken structs for each individual token,
264265 * or NIL if we reached EOL.
265266 */
266267static List *
267- next_field_expand (const char * filename , FILE * file )
268+ next_field_expand (const char * filename , char * * lineptr )
268269{
269270 char buf [MAX_TOKEN ];
270271 bool trailing_comma ;
@@ -273,7 +274,7 @@ next_field_expand(const char *filename, FILE *file)
273274
274275 do
275276 {
276- if (!next_token (file , buf , sizeof (buf ), & initial_quote , & trailing_comma ))
277+ if (!next_token (lineptr , buf , sizeof (buf ), & initial_quote , & trailing_comma ))
277278 break ;
278279
279280 /* Is this referencing a file? */
@@ -335,7 +336,7 @@ tokenize_inc_file(List *tokens,
335336 }
336337
337338 /* There is possible recursion here if the file contains @ */
338- linecxt = tokenize_file (inc_fullname , inc_file , & inc_lines , & inc_line_nums );
339+ linecxt = tokenize_file (inc_fullname , inc_file , & inc_lines , & inc_line_nums , NULL );
339340
340341 FreeFile (inc_file );
341342 pfree (inc_fullname );
@@ -364,8 +365,8 @@ tokenize_inc_file(List *tokens,
364365}
365366
366367/*
367- * Tokenize the given file, storing the resulting data into two Lists: a
368- * List of lines, and a List of line numbers .
368+ * Tokenize the given file, storing the resulting data into three Lists: a
369+ * List of lines, a List of line numbers, and a List of raw line contents .
369370 *
370371 * The list of lines is a triple-nested List structure. Each line is a List of
371372 * fields, and each field is a List of HbaTokens.
@@ -377,7 +378,7 @@ tokenize_inc_file(List *tokens,
377378 */
378379static MemoryContext
379380tokenize_file (const char * filename , FILE * file ,
380- List * * lines , List * * line_nums )
381+ List * * lines , List * * line_nums , List * * raw_lines )
381382{
382383 List * current_line = NIL ;
383384 List * current_field = NIL ;
@@ -396,30 +397,51 @@ tokenize_file(const char *filename, FILE *file,
396397
397398 while (!feof (file ) && !ferror (file ))
398399 {
399- current_field = next_field_expand (filename , file );
400+ char rawline [MAX_LINE ];
401+ char * lineptr ;
400402
401- /* add tokens to list, unless we are at EOL or comment start */
402- if (list_length (current_field ) > 0 )
403+ if (!fgets (rawline , sizeof (rawline ), file ))
404+ break ;
405+ if (strlen (rawline ) == MAX_LINE - 1 )
406+ /* Line too long! */
407+ ereport (ERROR ,
408+ (errcode (ERRCODE_CONFIG_FILE_ERROR ),
409+ errmsg ("authentication file line too long" ),
410+ errcontext ("line %d of configuration file \"%s\"" ,
411+ line_number , filename )));
412+
413+ /* Strip trailing linebreak from rawline */
414+ while (rawline [strlen (rawline )- 1 ] == '\n' ||
415+ rawline [strlen (rawline )- 1 ] == '\r' )
416+ rawline [strlen (rawline )- 1 ] = '\0' ;
417+
418+ lineptr = rawline ;
419+ while (strlen (lineptr ) > 0 )
403420 {
404- if (current_line == NIL )
405- {
406- /* make a new line List, record its line number */
407- current_line = lappend (current_line , current_field );
408- * lines = lappend (* lines , current_line );
409- * line_nums = lappend_int (* line_nums , line_number );
410- }
411- else
421+ current_field = next_field_expand (filename , & lineptr );
422+
423+ /* add tokens to list, unless we are at EOL or comment start */
424+ if (list_length (current_field ) > 0 )
412425 {
413- /* append tokens to current line's list */
414- current_line = lappend (current_line , current_field );
426+ if (current_line == NIL )
427+ {
428+ /* make a new line List, record its line number */
429+ current_line = lappend (current_line , current_field );
430+ * lines = lappend (* lines , current_line );
431+ * line_nums = lappend_int (* line_nums , line_number );
432+ if (raw_lines )
433+ * raw_lines = lappend (* raw_lines , pstrdup (rawline ));
434+ }
435+ else
436+ {
437+ /* append tokens to current line's list */
438+ current_line = lappend (current_line , current_field );
439+ }
415440 }
416441 }
417- else
418- {
419- /* we are at real or logical EOL, so force a new line List */
420- current_line = NIL ;
421- line_number ++ ;
422- }
442+ /* we are at real or logical EOL, so force a new line List */
443+ current_line = NIL ;
444+ line_number ++ ;
423445 }
424446
425447 MemoryContextSwitchTo (oldcxt );
@@ -815,7 +837,7 @@ check_same_host_or_net(SockAddr *raddr, IPCompareMethod method)
815837 * NULL.
816838 */
817839static HbaLine *
818- parse_hba_line (List * line , int line_num )
840+ parse_hba_line (List * line , int line_num , char * raw_line )
819841{
820842 char * str ;
821843 struct addrinfo * gai_result ;
@@ -831,6 +853,7 @@ parse_hba_line(List *line, int line_num)
831853
832854 parsedline = palloc0 (sizeof (HbaLine ));
833855 parsedline -> linenumber = line_num ;
856+ parsedline -> rawline = pstrdup (raw_line );
834857
835858 /* Check the record type. */
836859 field = list_head (line );
@@ -1761,8 +1784,10 @@ load_hba(void)
17611784 FILE * file ;
17621785 List * hba_lines = NIL ;
17631786 List * hba_line_nums = NIL ;
1787+ List * hba_raw_lines = NIL ;
17641788 ListCell * line ,
1765- * line_num ;
1789+ * line_num ,
1790+ * raw_line ;
17661791 List * new_parsed_lines = NIL ;
17671792 bool ok = true;
17681793 MemoryContext linecxt ;
@@ -1779,7 +1804,7 @@ load_hba(void)
17791804 return false;
17801805 }
17811806
1782- linecxt = tokenize_file (HbaFileName , file , & hba_lines , & hba_line_nums );
1807+ linecxt = tokenize_file (HbaFileName , file , & hba_lines , & hba_line_nums , & hba_raw_lines );
17831808 FreeFile (file );
17841809
17851810 /* Now parse all the lines */
@@ -1789,11 +1814,11 @@ load_hba(void)
17891814 ALLOCSET_DEFAULT_MINSIZE ,
17901815 ALLOCSET_DEFAULT_MAXSIZE );
17911816 oldcxt = MemoryContextSwitchTo (hbacxt );
1792- forboth (line , hba_lines , line_num , hba_line_nums )
1817+ forthree (line , hba_lines , line_num , hba_line_nums , raw_line , hba_raw_lines )
17931818 {
17941819 HbaLine * newline ;
17951820
1796- if ((newline = parse_hba_line (lfirst (line ), lfirst_int (line_num ))) == NULL )
1821+ if ((newline = parse_hba_line (lfirst (line ), lfirst_int (line_num ), lfirst ( raw_line ) )) == NULL )
17971822 {
17981823 /*
17991824 * Parse error in the file, so indicate there's a problem. NB: a
@@ -2153,7 +2178,7 @@ load_ident(void)
21532178 return false;
21542179 }
21552180
2156- linecxt = tokenize_file (IdentFileName , file , & ident_lines , & ident_line_nums );
2181+ linecxt = tokenize_file (IdentFileName , file , & ident_lines , & ident_line_nums , NULL );
21572182 FreeFile (file );
21582183
21592184 /* Now parse all the lines */
0 commit comments