diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index a773381..42aaea8 100644
*** a/src/port/snprintf.c
--- b/src/port/snprintf.c
***************
*** 110,115 ****
--- 110,129 ----
  #undef	printf
  
  /*
+  * If this file is compiled with SNPRINTF_VALIDATE defined, it doesn't
+  * provide any of the normal *printf functions, but instead exports
+  * a function "pg_validate_printf_format()" that just detects whether a
+  * supplied format string is syntactically valid.  We implement that
+  * by running the normal snprintf code with a fake output buffer, and
+  * suppressing all attempts to fetch variable arguments (since those
+  * won't be there).
+  */
+ #ifdef SNPRINTF_VALIDATE
+ #undef va_arg
+ #define va_arg(args, type)  ((type) 0)
+ #endif
+ 
+ /*
   * Info about where the formatted output is going.
   *
   * dopr and subroutines will not write at/past bufend, but snprintf
*************** static void dopr(PrintfTarget *target, c
*** 170,175 ****
--- 184,191 ----
   * they not change the value of "errno" before reaching dopr().
   */
  
+ #ifndef SNPRINTF_VALIDATE
+ 
  int
  pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
  {
*************** pg_printf(const char *fmt,...)
*** 290,295 ****
--- 306,335 ----
  	return len;
  }
  
+ #else							/* SNPRINTF_VALIDATE */
+ 
+ /*
+  * Returns 1 if "fmt" is syntactically valid, -1 if not.
+  * In the latter case, errno is set (but it'll always be EINVAL).
+  */
+ int
+ pg_validate_printf_format(const char *fmt)
+ {
+ 	/* Code is basically the same as pg_vsnprintf with NULL str argument */
+ 	PrintfTarget target;
+ 	char		onebyte[1];
+ 
+ 	target.bufstart = target.bufptr = onebyte;
+ 	target.bufend = onebyte;
+ 	target.stream = NULL;
+ 	target.nchars = 0;
+ 	target.failed = false;
+ 	dopr(&target, fmt, NULL);
+ 	return target.failed ? -1 : 1;
+ }
+ 
+ #endif							/* SNPRINTF_VALIDATE */
+ 
  /*
   * Attempt to write the entire buffer to target->stream; discard the entire
   * buffer in any case.  Call this only when target->stream is defined.
*************** dopr(PrintfTarget *target, const char *f
*** 438,445 ****
--- 478,489 ----
  		if (*format == 's')
  		{
  			format++;
+ #ifndef SNPRINTF_VALIDATE
  			strvalue = va_arg(args, char *);
  			Assert(strvalue != NULL);
+ #else
+ 			strvalue = "";
+ #endif
  			dostr(strvalue, strlen(strvalue), target);
  			if (target->failed)
  				break;
*************** nextch2:
*** 666,677 ****
--- 710,726 ----
  					else
  						fieldwidth = accum;
  				}
+ #ifndef SNPRINTF_VALIDATE
  				if (have_dollar)
  					strvalue = argvalues[fmtpos].cptr;
  				else
  					strvalue = va_arg(args, char *);
  				/* Whine if someone tries to print a NULL string */
  				Assert(strvalue != NULL);
+ #else
+ 				/* va_arg would return NULL, so inject empty string instead */
+ 				strvalue = "";
+ #endif
  				fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
  					   target);
  				break;
*************** fail:
*** 1252,1257 ****
--- 1301,1308 ----
  	target->failed = true;
  }
  
+ #ifndef SNPRINTF_VALIDATE
+ 
  /*
   * Nonstandard entry point to print a double value efficiently.
   *
*************** fail:
*** 1352,1357 ****
--- 1403,1410 ----
  								 + target.nchars);
  }
  
+ #endif							/* SNPRINTF_VALIDATE */
+ 
  
  static void
  dostr(const char *str, int slen, PrintfTarget *target)
diff --git a/src/port/test_po_file.c b/src/port/test_po_file.c
index ...8dc063c .
*** a/src/port/test_po_file.c
--- b/src/port/test_po_file.c
***************
*** 0 ****
--- 1,150 ----
+ /*-------------------------------------------------------------------------
+  *
+  * test_po_file.c
+  *	  Test messages in a .po file to see if our version of snprintf likes them.
+  *
+  * Copyright (c) 2018, PostgreSQL Global Development Group
+  *
+  *
+  * IDENTIFICATION
+  *	  src/port/test_po_file.c
+  *
+  *-------------------------------------------------------------------------
+  */
+ 
+ #include "c.h"
+ 
+ #include <gettext-po.h>
+ 
+ /* snprintf.c will provide this below */
+ extern int	pg_validate_printf_format(const char *fmt);
+ 
+ 
+ /* Error handlers required by recent libgettextpo versions */
+ static void
+ xerror(int severity,
+ 	   po_message_t message,
+ 	   const char *filename, size_t lineno, size_t column,
+ 	   int multiline_p, const char *message_text)
+ {
+ 	fprintf(stderr, "PO error: %s\n", message_text);
+ 	if (filename)
+ 		fprintf(stderr, "Error occurred in file \"%s\" at line %d:\n",
+ 				filename, (int) lineno);
+ 	if (severity == PO_SEVERITY_FATAL_ERROR)
+ 		exit(1);
+ }
+ 
+ static void
+ xerror2(int severity,
+ 		po_message_t message1,
+ 		const char *filename1, size_t lineno1, size_t column1,
+ 		int multiline_p1, const char *message_text1,
+ 		po_message_t message2,
+ 		const char *filename2, size_t lineno2, size_t column2,
+ 		int multiline_p2, const char *message_text2)
+ {
+ 	fprintf(stderr, "PO error: %s ...\n", message_text1);
+ 	if (filename1)
+ 		fprintf(stderr, "Error occurred in file \"%s\" at line %d:\n",
+ 				filename1, (int) lineno1);
+ 	fprintf(stderr, "PO error: ... %s\n", message_text2);
+ 	if (filename2)
+ 		fprintf(stderr, "Error occurred in file \"%s\" at line %d:\n",
+ 				filename2, (int) lineno2);
+ 	if (severity == PO_SEVERITY_FATAL_ERROR)
+ 		exit(1);
+ }
+ 
+ static const struct po_xerror_handler handler = {
+ 	xerror, xerror2
+ };
+ 
+ 
+ /*
+  * Main program.
+  *
+  * Test each .po file named on the command line.
+  */
+ int
+ main(int argc, char **argv)
+ {
+ 	for (int i = 1; i < argc; i++)
+ 	{
+ 		const char *filename = argv[i];
+ 		po_file_t	file = po_file_read(filename, &handler);
+ 		const char *const *domains;
+ 		const char *const *domainp;
+ 
+ 		if (file == NULL)
+ 		{
+ 			fprintf(stderr, "could not open file \"%s\": %s\n",
+ 					filename, strerror(errno));
+ 			exit(1);
+ 		}
+ 
+ 		domains = po_file_domains(file);
+ 		for (domainp = domains; *domainp; domainp++)
+ 		{
+ 			const char *domain = *domainp;
+ 			po_message_iterator_t iterator = po_message_iterator(file, domain);
+ 
+ 			for (;;)
+ 			{
+ 				po_message_t message = po_next_message(iterator);
+ 				po_filepos_t pos;
+ 				char		location[256];
+ 				const char *fmt;
+ 
+ 				if (message == NULL)
+ 					break;
+ 
+ 				if (!po_message_is_format(message, "c-format"))
+ 					continue;
+ 
+ 				pos = po_message_filepos(message, 0);
+ 				if (pos)
+ 					snprintf(location, sizeof(location), "for %s:%ld",
+ 							 po_filepos_file(pos),
+ 							 (long) po_filepos_start_line(pos));
+ 				else
+ 					strcpy(location, "unknown location");
+ 
+ 				fmt = po_message_msgid(message);
+ 				if (fmt && pg_validate_printf_format(fmt) < 0)
+ 					fprintf(stderr, "invalid format string in file \"%s\" %s\n\"%s\"\n",
+ 							filename, location, fmt);
+ 				fmt = po_message_msgid_plural(message);
+ 				if (fmt && pg_validate_printf_format(fmt) < 0)
+ 					fprintf(stderr, "invalid format string in file \"%s\" %s\n\"%s\"\n",
+ 							filename, location, fmt);
+ 				fmt = po_message_msgstr(message);
+ 				if (fmt && pg_validate_printf_format(fmt) < 0)
+ 					fprintf(stderr, "invalid format string in file \"%s\" %s\n\"%s\"\n",
+ 							filename, location, fmt);
+ 				for (int ndx = 0;; ndx++)
+ 				{
+ 					fmt = po_message_msgstr_plural(message, ndx);
+ 					if (!fmt)
+ 						break;
+ 					if (pg_validate_printf_format(fmt) < 0)
+ 						fprintf(stderr, "invalid format string in file \"%s\" %s\n\"%s\"\n",
+ 								filename, location, fmt);
+ 				}
+ 			}
+ 			po_message_iterator_free(iterator);
+ 		}
+ 		po_file_free(file);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * Now include snprintf.c with the desired variant compilation flag.
+  * We put this at the end so that its messing about with #define's
+  * won't mess up code in this file.
+  */
+ #define SNPRINTF_VALIDATE 1
+ 
+ #include "snprintf.c"
