*** a/src/backend/utils/adt/json.c
--- b/src/backend/utils/adt/json.c
***************
*** 212,217 **** makeJsonLexContext(char *json, bool need_escapes)
--- 212,218 ----
  
  	lex->input = lex->token_terminator = lex->line_start = json;
  	lex->line_number = 1;
+ 	lex->input_length = strlen(json);
  	if (need_escapes)
  		lex->strval = makeStringInfo();
  	return lex;
***************
*** 398,416 **** static void
  json_lex(JsonLexContext *lex)
  {
  	char	   *s;
! 
  	/* Skip leading whitespace. */
  	s = lex->token_terminator;
! 	while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
  	{
  		if (*s == '\n')
  			++lex->line_number;
  		++s;
  	}
  	lex->token_start = s;
  
  	/* Determine token type. */
! 	if (*s == '\0')
  	{
  		lex->token_start = NULL;
  		lex->prev_token_terminator = lex->token_terminator;
--- 399,420 ----
  json_lex(JsonLexContext *lex)
  {
  	char	   *s;
! 	int         len;
  	/* Skip leading whitespace. */
  	s = lex->token_terminator;
! 	len = s - lex->input;
! 	while (len < lex->input_length &&
! 		   (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
  	{
  		if (*s == '\n')
  			++lex->line_number;
  		++s;
+ 		++len;
  	}
  	lex->token_start = s;
  
  	/* Determine token type. */
! 	if (len >= lex->input_length)
  	{
  		lex->token_start = NULL;
  		lex->prev_token_terminator = lex->token_terminator;
***************
*** 476,482 **** json_lex(JsonLexContext *lex)
  		 * whole word as an unexpected token, rather than just some
  		 * unintuitive prefix thereof.
  		 */
! 		for (p = s; JSON_ALPHANUMERIC_CHAR(*p); p++)
  			 /* skip */ ;
  
  		/*
--- 480,486 ----
  		 * whole word as an unexpected token, rather than just some
  		 * unintuitive prefix thereof.
  		 */
! 		for (p = s; JSON_ALPHANUMERIC_CHAR(*p) && p - s < lex->input_length - len; p++)
  			 /* skip */ ;
  
  		/*
***************
*** 519,539 **** static void
  json_lex_string(JsonLexContext *lex)
  {
  	char	   *s;
! 
  	if (lex->strval != NULL)
  		resetStringInfo(lex->strval);
  
! 	for (s = lex->token_start + 1; *s != '"'; s++)
  	{
! 		/* Per RFC4627, these characters MUST be escaped. */
! 		if ((unsigned char) *s < 32)
  		{
! 			/* A NUL byte marks the (premature) end of the string. */
! 			if (*s == '\0')
! 			{
! 				lex->token_terminator = s;
! 				report_invalid_token(lex);
! 			}
  			/* Since *s isn't printable, exclude it from the context string */
  			lex->token_terminator = s;
  			ereport(ERROR,
--- 523,545 ----
  json_lex_string(JsonLexContext *lex)
  {
  	char	   *s;
! 	int         len;
  	if (lex->strval != NULL)
  		resetStringInfo(lex->strval);
  
! 	len = lex->token_start - lex->input;
! 	len++;
! 	for (s = lex->token_start + 1; *s != '"'; s++, len++)
  	{
! 		/* Premature end of the string. */
! 		if (len >= lex->input_length)
  		{
! 			lex->token_terminator = s;
! 			report_invalid_token(lex);
! 		}
! 		else if ((unsigned char) *s < 32)
! 		{
! 			/* Per RFC4627, these characters MUST be escaped. */
  			/* Since *s isn't printable, exclude it from the context string */
  			lex->token_terminator = s;
  			ereport(ERROR,
***************
*** 547,553 **** json_lex_string(JsonLexContext *lex)
  		{
  			/* OK, we have an escape character. */
  			s++;
! 			if (*s == '\0')
  			{
  				lex->token_terminator = s;
  				report_invalid_token(lex);
--- 553,560 ----
  		{
  			/* OK, we have an escape character. */
  			s++;
! 			len++;
! 			if (len >= lex->input_length)
  			{
  				lex->token_terminator = s;
  				report_invalid_token(lex);
***************
*** 560,566 **** json_lex_string(JsonLexContext *lex)
  				for (i = 1; i <= 4; i++)
  				{
  					s++;
! 					if (*s == '\0')
  					{
  						lex->token_terminator = s;
  						report_invalid_token(lex);
--- 567,574 ----
  				for (i = 1; i <= 4; i++)
  				{
  					s++;
! 					len++;
! 					if (len >= lex->input_length)
  					{
  						lex->token_terminator = s;
  						report_invalid_token(lex);
***************
*** 690,696 **** json_lex_number(JsonLexContext *lex, char *s)
--- 698,706 ----
  {
  	bool		error = false;
  	char	   *p;
+ 	int         len;
  
+ 	len = s - lex->input;
  	/* Part (1): leading sign indicator. */
  	/* Caller already did this for us; so do nothing. */
  
***************
*** 702,741 **** json_lex_number(JsonLexContext *lex, char *s)
  		do
  		{
  			s++;
! 		} while (*s >= '0' && *s <= '9');
  	}
  	else
  		error = true;
  
  	/* Part (3): parse optional decimal portion. */
! 	if (*s == '.')
  	{
  		s++;
! 		if (*s < '0' || *s > '9')
  			error = true;
  		else
  		{
  			do
  			{
  				s++;
! 			} while (*s >= '0' && *s <= '9');
  		}
  	}
  
  	/* Part (4): parse optional exponent. */
! 	if (*s == 'e' || *s == 'E')
  	{
  		s++;
! 		if (*s == '+' || *s == '-')
  			s++;
! 		if (*s < '0' || *s > '9')
  			error = true;
  		else
  		{
  			do
  			{
  				s++;
! 			} while (*s >= '0' && *s <= '9');
  		}
  	}
  
--- 712,759 ----
  		do
  		{
  			s++;
! 			len++;
! 		} while (*s >= '0' && *s <= '9' && len < lex->input_length);
  	}
  	else
  		error = true;
  
  	/* Part (3): parse optional decimal portion. */
! 	if (len < lex->input_length && *s == '.')
  	{
  		s++;
! 		len++;
! 		if (len == lex->input_length || *s < '0' || *s > '9')
  			error = true;
  		else
  		{
  			do
  			{
  				s++;
! 				len++;
! 			} while (*s >= '0' && *s <= '9' && len < lex->input_length);
  		}
  	}
  
  	/* Part (4): parse optional exponent. */
! 	if (len < lex->input_length && (*s == 'e' || *s == 'E'))
  	{
  		s++;
! 		len++;
! 		if (len < lex->input_length && (*s == '+' || *s == '-'))
! 		{
  			s++;
! 			len++;
! 		}
! 		if (len == lex->input_length || *s < '0' || *s > '9')
  			error = true;
  		else
  		{
  			do
  			{
  				s++;
! 				len++;
! 			} while (len < lex->input_length && *s >= '0' && *s <= '9');
  		}
  	}
  
***************
*** 744,750 **** json_lex_number(JsonLexContext *lex, char *s)
  	 * here should be considered part of the token for error-reporting
  	 * purposes.
  	 */
! 	for (p = s; JSON_ALPHANUMERIC_CHAR(*p); p++)
  		error = true;
  	lex->prev_token_terminator = lex->token_terminator;
  	lex->token_terminator = p;
--- 762,768 ----
  	 * here should be considered part of the token for error-reporting
  	 * purposes.
  	 */
! 	for (p = s; JSON_ALPHANUMERIC_CHAR(*p) && len < lex->input_length; p++, len++)
  		error = true;
  	lex->prev_token_terminator = lex->token_terminator;
  	lex->token_terminator = p;
*** a/src/include/utils/jsonapi.h
--- b/src/include/utils/jsonapi.h
***************
*** 36,41 **** typedef enum
--- 36,42 ----
  typedef struct JsonLexContext
  {
  	char	   *input;
+ 	int			input_length;
  	char	   *token_start;
  	char	   *token_terminator;
  	char	   *prev_token_terminator;
