@@ -339,6 +339,210 @@ appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
339
339
}
340
340
341
341
342
+ /*
343
+ * Append the given string to the shell command being built in the buffer,
344
+ * with suitable shell-style quoting to create exactly one argument.
345
+ *
346
+ * Forbid LF or CR characters, which have scant practical use beyond designing
347
+ * security breaches. The Windows command shell is unusable as a conduit for
348
+ * arguments containing LF or CR characters. A future major release should
349
+ * reject those characters in CREATE ROLE and CREATE DATABASE, because use
350
+ * there eventually leads to errors here.
351
+ */
352
+ void
353
+ appendShellString (PQExpBuffer buf , const char * str )
354
+ {
355
+ const char * p ;
356
+
357
+ #ifndef WIN32
358
+ appendPQExpBufferChar (buf , '\'' );
359
+ for (p = str ; * p ; p ++ )
360
+ {
361
+ if (* p == '\n' || * p == '\r' )
362
+ {
363
+ fprintf (stderr ,
364
+ _ ("shell command argument contains a newline or carriage return: \"%s\"\n" ),
365
+ str );
366
+ exit (EXIT_FAILURE );
367
+ }
368
+
369
+ if (* p == '\'' )
370
+ appendPQExpBufferStr (buf , "'\"'\"'" );
371
+ else
372
+ appendPQExpBufferChar (buf , * p );
373
+ }
374
+ appendPQExpBufferChar (buf , '\'' );
375
+ #else /* WIN32 */
376
+ int backslash_run_length = 0 ;
377
+
378
+ /*
379
+ * A Windows system() argument experiences two layers of interpretation.
380
+ * First, cmd.exe interprets the string. Its behavior is undocumented,
381
+ * but a caret escapes any byte except LF or CR that would otherwise have
382
+ * special meaning. Handling of a caret before LF or CR differs between
383
+ * "cmd.exe /c" and other modes, and it is unusable here.
384
+ *
385
+ * Second, the new process parses its command line to construct argv (see
386
+ * https://msdn.microsoft.com/en-us/library/17w5ykft.aspx). This treats
387
+ * backslash-double quote sequences specially.
388
+ */
389
+ appendPQExpBufferStr (buf , "^\"" );
390
+ for (p = str ; * p ; p ++ )
391
+ {
392
+ if (* p == '\n' || * p == '\r' )
393
+ {
394
+ fprintf (stderr ,
395
+ _ ("shell command argument contains a newline or carriage return: \"%s\"\n" ),
396
+ str );
397
+ exit (EXIT_FAILURE );
398
+ }
399
+
400
+ /* Change N backslashes before a double quote to 2N+1 backslashes. */
401
+ if (* p == '"' )
402
+ {
403
+ while (backslash_run_length )
404
+ {
405
+ appendPQExpBufferStr (buf , "^\\" );
406
+ backslash_run_length -- ;
407
+ }
408
+ appendPQExpBufferStr (buf , "^\\" );
409
+ }
410
+ else if (* p == '\\' )
411
+ backslash_run_length ++ ;
412
+ else
413
+ backslash_run_length = 0 ;
414
+
415
+ /*
416
+ * Decline to caret-escape the most mundane characters, to ease
417
+ * debugging and lest we approach the command length limit.
418
+ */
419
+ if (!((* p >= 'a' && * p <= 'z' ) ||
420
+ (* p >= 'A' && * p <= 'Z' ) ||
421
+ (* p >= '0' && * p <= '9' )))
422
+ appendPQExpBufferChar (buf , '^' );
423
+ appendPQExpBufferChar (buf , * p );
424
+ }
425
+
426
+ /*
427
+ * Change N backslashes at end of argument to 2N backslashes, because they
428
+ * precede the double quote that terminates the argument.
429
+ */
430
+ while (backslash_run_length )
431
+ {
432
+ appendPQExpBufferStr (buf , "^\\" );
433
+ backslash_run_length -- ;
434
+ }
435
+ appendPQExpBufferStr (buf , "^\"" );
436
+ #endif /* WIN32 */
437
+ }
438
+
439
+
440
+ /*
441
+ * Append the given string to the buffer, with suitable quoting for passing
442
+ * the string as a value, in a keyword/pair value in a libpq connection
443
+ * string
444
+ */
445
+ void
446
+ appendConnStrVal (PQExpBuffer buf , const char * str )
447
+ {
448
+ const char * s ;
449
+ bool needquotes ;
450
+
451
+ /*
452
+ * If the string is one or more plain ASCII characters, no need to quote
453
+ * it. This is quite conservative, but better safe than sorry.
454
+ */
455
+ needquotes = true;
456
+ for (s = str ; * s ; s ++ )
457
+ {
458
+ if (!((* s >= 'a' && * s <= 'z' ) || (* s >= 'A' && * s <= 'Z' ) ||
459
+ (* s >= '0' && * s <= '9' ) || * s == '_' || * s == '.' ))
460
+ {
461
+ needquotes = true;
462
+ break ;
463
+ }
464
+ needquotes = false;
465
+ }
466
+
467
+ if (needquotes )
468
+ {
469
+ appendPQExpBufferChar (buf , '\'' );
470
+ while (* str )
471
+ {
472
+ /* ' and \ must be escaped by to \' and \\ */
473
+ if (* str == '\'' || * str == '\\' )
474
+ appendPQExpBufferChar (buf , '\\' );
475
+
476
+ appendPQExpBufferChar (buf , * str );
477
+ str ++ ;
478
+ }
479
+ appendPQExpBufferChar (buf , '\'' );
480
+ }
481
+ else
482
+ appendPQExpBufferStr (buf , str );
483
+ }
484
+
485
+
486
+ /*
487
+ * Append a psql meta-command that connects to the given database with the
488
+ * then-current connection's user, host and port.
489
+ */
490
+ void
491
+ appendPsqlMetaConnect (PQExpBuffer buf , const char * dbname )
492
+ {
493
+ const char * s ;
494
+ bool complex ;
495
+
496
+ /*
497
+ * If the name is plain ASCII characters, emit a trivial "\connect "foo"".
498
+ * For other names, even many not technically requiring it, skip to the
499
+ * general case. No database has a zero-length name.
500
+ */
501
+ complex = false;
502
+ for (s = dbname ; * s ; s ++ )
503
+ {
504
+ if (* s == '\n' || * s == '\r' )
505
+ {
506
+ fprintf (stderr ,
507
+ _ ("database name contains a newline or carriage return: \"%s\"\n" ),
508
+ dbname );
509
+ exit (EXIT_FAILURE );
510
+ }
511
+
512
+ if (!((* s >= 'a' && * s <= 'z' ) || (* s >= 'A' && * s <= 'Z' ) ||
513
+ (* s >= '0' && * s <= '9' ) || * s == '_' || * s == '.' ))
514
+ {
515
+ complex = true;
516
+ }
517
+ }
518
+
519
+ appendPQExpBufferStr (buf , "\\connect " );
520
+ if (complex )
521
+ {
522
+ PQExpBufferData connstr ;
523
+
524
+ initPQExpBuffer (& connstr );
525
+ appendPQExpBuffer (& connstr , "dbname=" );
526
+ appendConnStrVal (& connstr , dbname );
527
+
528
+ appendPQExpBuffer (buf , "-reuse-previous=on " );
529
+
530
+ /*
531
+ * As long as the name does not contain a newline, SQL identifier
532
+ * quoting satisfies the psql meta-command parser. Prefer not to
533
+ * involve psql-interpreted single quotes, which behaved differently
534
+ * before PostgreSQL 9.2.
535
+ */
536
+ appendPQExpBufferStr (buf , fmtId (connstr .data ));
537
+
538
+ termPQExpBuffer (& connstr );
539
+ }
540
+ else
541
+ appendPQExpBufferStr (buf , fmtId (dbname ));
542
+ appendPQExpBufferChar (buf , '\n' );
543
+ }
544
+
545
+
342
546
/*
343
547
* Convert a bytea value (presented as raw bytes) to an SQL string literal
344
548
* and append it to the given buffer. We assume the specified
0 commit comments