Re: [PATCHES] appendStringInfoString() micro-opt

2004-01-30 Thread Tom Lane
Neil Conway <[EMAIL PROTECTED]> writes:
> It occurred to me that there is a potential security problem with code
> like:

> char *my_str;
> my_str = read_from_an_untrusted_source();
> appendStringInfo(buf, my_str);

> If my_str contains any formatting characters, this crashes the
> backend. I'm not sure if there are any actual exploitable instances of
> this in the backend, but the above unsafe coding practise is fairly
> common.

It is?  I thought I'd gone around and checked for that.  If you see any
remaining cases then I'd say they are must-fix items.

regards, tom lane

---(end of broadcast)---
TIP 4: Don't 'kill -9' the postmaster


Re: [PATCHES] appendStringInfoString() micro-opt

2004-01-30 Thread Neil Conway
Neil Conway <[EMAIL PROTECTED]> writes:
> I'll put this on the back-burner for now, and repost a complete
> patch later if I get around to it.

I've applied the following patch (since I'd already gone ahead and
done the work) that replaces appendStringInfo(buf, "%s", str) with
appendStringInfoString(buf, str)

It occurred to me that there is a potential security problem with code
like:

char *my_str;
my_str = read_from_an_untrusted_source();
appendStringInfo(buf, my_str);

If my_str contains any formatting characters, this crashes the
backend. I'm not sure if there are any actual exploitable instances of
this in the backend, but the above unsafe coding practise is fairly
common.

-Neil

Index: src/backend/commands/explain.c
===
RCS file: /var/lib/cvs/pgsql-server/src/backend/commands/explain.c,v
retrieving revision 1.118
diff -c -r1.118 explain.c
*** src/backend/commands/explain.c	29 Nov 2003 19:51:47 -	1.118
--- src/backend/commands/explain.c	31 Jan 2004 04:49:13 -
***
*** 1002,1008 
  		/* And add to str */
  		if (keyno > 0)
  			appendStringInfo(str, ", ");
! 		appendStringInfo(str, "%s", exprstr);
  	}
  
  	appendStringInfo(str, "\n");
--- 1002,1008 
  		/* And add to str */
  		if (keyno > 0)
  			appendStringInfo(str, ", ");
! 		appendStringInfoString(str, exprstr);
  	}
  
  	appendStringInfo(str, "\n");
Index: src/backend/nodes/outfuncs.c
===
RCS file: /var/lib/cvs/pgsql-server/src/backend/nodes/outfuncs.c,v
retrieving revision 1.231
diff -c -r1.231 outfuncs.c
*** src/backend/nodes/outfuncs.c	22 Jan 2004 00:34:31 -	1.231
--- src/backend/nodes/outfuncs.c	31 Jan 2004 04:49:38 -
***
*** 1427,1433 
  			 * We assume the value is a valid numeric literal and so does
  			 * not need quoting.
  			 */
! 			appendStringInfo(str, "%s", value->val.str);
  			break;
  		case T_String:
  			appendStringInfoChar(str, '"');
--- 1427,1433 
  			 * We assume the value is a valid numeric literal and so does
  			 * not need quoting.
  			 */
! 			appendStringInfoString(str, value->val.str);
  			break;
  		case T_String:
  			appendStringInfoChar(str, '"');
***
*** 1436,1442 
  			break;
  		case T_BitString:
  			/* internal representation already has leading 'b' */
! 			appendStringInfo(str, "%s", value->val.str);
  			break;
  		default:
  			elog(ERROR, "unrecognized node type: %d", (int) value->type);
--- 1436,1442 
  			break;
  		case T_BitString:
  			/* internal representation already has leading 'b' */
! 			appendStringInfoString(str, value->val.str);
  			break;
  		default:
  			elog(ERROR, "unrecognized node type: %d", (int) value->type);
Index: src/backend/utils/adt/regproc.c
===
RCS file: /var/lib/cvs/pgsql-server/src/backend/utils/adt/regproc.c,v
retrieving revision 1.85
diff -c -r1.85 regproc.c
*** src/backend/utils/adt/regproc.c	29 Nov 2003 19:51:59 -	1.85
--- src/backend/utils/adt/regproc.c	31 Jan 2004 04:49:56 -
***
*** 340,346 
  
  			if (i > 0)
  appendStringInfoChar(&buf, ',');
! 			appendStringInfo(&buf, "%s", format_type_be(thisargtype));
  		}
  		appendStringInfoChar(&buf, ')');
  
--- 340,346 
  
  			if (i > 0)
  appendStringInfoChar(&buf, ',');
! 			appendStringInfoString(&buf, format_type_be(thisargtype));
  		}
  		appendStringInfoChar(&buf, ')');
  
Index: src/backend/utils/adt/ruleutils.c
===
RCS file: /var/lib/cvs/pgsql-server/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.161
diff -c -r1.161 ruleutils.c
*** src/backend/utils/adt/ruleutils.c	28 Dec 2003 21:57:37 -	1.161
--- src/backend/utils/adt/ruleutils.c	31 Jan 2004 04:55:19 -
***
*** 752,758 
  
  			attname = get_relid_attribute_name(indrelid, attnum);
  			if (!colno || colno == keyno + 1)
! appendStringInfo(&buf, "%s", quote_identifier(attname));
  			keycoltype = get_atttype(indrelid, attnum);
  		}
  		else
--- 752,758 
  
  			attname = get_relid_attribute_name(indrelid, attnum);
  			if (!colno || colno == keyno + 1)
! appendStringInfoString(&buf, quote_identifier(attname));
  			keycoltype = get_atttype(indrelid, attnum);
  		}
  		else
***
*** 772,778 
  /* Need parens if it's not a bare function call */
  if (indexkey && IsA(indexkey, FuncExpr) &&
  	((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
! 	appendStringInfo(&buf, "%s", str);
  else
  	appendStringInfo(&buf, "(%s)", str);
  			}
--- 772,778 
  /* Need parens if it's not a bare function call */
  if (indexkey && IsA(indexkey, FuncExpr) &&
  	((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
! 	appendStringInfoString(&buf, str);
  else
  	appendStringInfo(&buf

Re: [PATCHES] appendStringInfoString() micro-opt

2004-01-26 Thread Tom Lane
Bruce Momjian <[EMAIL PROTECTED]> writes:
> Tom Lane wrote:
>> I'm not objecting to your doing it, exactly, just suggesting that there
>> are better things to spend your time on.

> Of course, if it makes the code clearer, that is a win in itself.

Sure, but I can't see that there's any gain in readability here ...

regards, tom lane

---(end of broadcast)---
TIP 6: Have you searched our list archives?

   http://archives.postgresql.org


Re: [PATCHES] appendStringInfoString() micro-opt

2004-01-26 Thread Bruce Momjian
Tom Lane wrote:
> Neil Conway <[EMAIL PROTECTED]> writes:
> > This patch replaces a bunch of call sites of appendStringInfo() with
> > appendStringInfoString().
> 
> I doubt this saves enough cycles to be worth doing, but if it floats
> your boat ...
> 
> When I'm tempted to make a dubious micro-optimization, I always ask
> myself "is it likely that the sum of all machine time saved by this
> change will exceed the amount of person-time I am about to put into
> making it?"  Given the number of places you're talking about touching,
> and the fact that I've never seen appendStringInfo placing high on a
> profile, I suspect this doesn't pass that test.
> 
> I'm not objecting to your doing it, exactly, just suggesting that there
> are better things to spend your time on.

Of course, if it makes the code clearer, that is a win in itself.

-- 
  Bruce Momjian|  http://candle.pha.pa.us
  [EMAIL PROTECTED]   |  (610) 359-1001
  +  If your life is a hard drive, |  13 Roberts Road
  +  Christ can be your backup.|  Newtown Square, Pennsylvania 19073

---(end of broadcast)---
TIP 8: explain analyze is your friend


Re: [PATCHES] appendStringInfoString() micro-opt

2004-01-25 Thread Neil Conway
Tom Lane <[EMAIL PROTECTED]> writes:
> I'm not objecting to your doing it, exactly, just suggesting that
> there are better things to spend your time on.

Heh, probably true :-)

I'll put this on the back-burner for now, and repost a complete patch
later if I get around to it.

> This I would object to, since it creates a risk of failure if anyone
> is incautious enough to write a non-constant argument to
> appendStringInfoString.

Agreed.

(Semi-OT note: allowing the user to extend the compiler to enforce
rules like this is a cool idea: http://metacomp.stanford.edu/)

-Neil


---(end of broadcast)---
TIP 3: if posting/reading through Usenet, please send an appropriate
  subscribe-nomail command to [EMAIL PROTECTED] so that your
  message can get through to the mailing list cleanly


Re: [PATCHES] appendStringInfoString() micro-opt

2004-01-25 Thread Tom Lane
Neil Conway <[EMAIL PROTECTED]> writes:
> This patch replaces a bunch of call sites of appendStringInfo() with
> appendStringInfoString().

I doubt this saves enough cycles to be worth doing, but if it floats
your boat ...

When I'm tempted to make a dubious micro-optimization, I always ask
myself "is it likely that the sum of all machine time saved by this
change will exceed the amount of person-time I am about to put into
making it?"  Given the number of places you're talking about touching,
and the fact that I've never seen appendStringInfo placing high on a
profile, I suspect this doesn't pass that test.

I'm not objecting to your doing it, exactly, just suggesting that there
are better things to spend your time on.

> I was tempted to make appendStringInfoString() a macro, since (a) it's
> just one line of code (b) I'd expect plenty of compilers to be smart
> enough to optimize-out a strlen() on a string-literal arg. The
> downside is that it would require that appendStringInfoString()
> evaluate its arguments more than once. Any comments on whether this is
> worth doing?

This I would object to, since it creates a risk of failure if anyone
is incautious enough to write a non-constant argument to
appendStringInfoString.  As soon as you factor any future debugging
into the equation, the probability that you've made a net savings of
time drops to nil :-(.  You have to have a *very* large payback to
justify putting that kind of booby-trap into the code, and the payback
from this change is not only not large, there's no evidence that it'd
even be measurable.

regards, tom lane

---(end of broadcast)---
TIP 6: Have you searched our list archives?

   http://archives.postgresql.org


[PATCHES] appendStringInfoString() micro-opt

2004-01-24 Thread Neil Conway
This patch replaces a bunch of call sites of appendStringInfo() with
appendStringInfoString(). (For those without the code in front of
you, the difference between these two functions is that the former
takes a sprintf-style format string and a variable list of arguments,
whereas the latter just takes a single NUL-terminated string;
therefore, the latter is faster if you're just appending a single
string to the buffer).

For the sake of minimizing how much of my time I've wasted if someone
objects, this patch only changes a portion of the call sites that
could be changed; I'll do the rest before committing the patch.

I was tempted to make appendStringInfoString() a macro, since (a) it's
just one line of code (b) I'd expect plenty of compilers to be smart
enough to optimize-out a strlen() on a string-literal arg. The
downside is that it would require that appendStringInfoString()
evaluate its arguments more than once. Any comments on whether this is
worth doing?

Unless anyone objects, I intend to apply the full version of this
patch within 48 hours.

-Neil
Index: src/backend/commands/explain.c
===
RCS file: /var/lib/cvs/pgsql-server/src/backend/commands/explain.c,v
retrieving revision 1.118
diff -c -r1.118 explain.c
*** src/backend/commands/explain.c	29 Nov 2003 19:51:47 -	1.118
--- src/backend/commands/explain.c	25 Jan 2004 03:32:01 -
***
*** 589,595 
  			 planstate->instrument->nloops);
  		}
  		else if (es->printAnalyze)
! 			appendStringInfo(str, " (never executed)");
  	}
  	appendStringInfoChar(str, '\n');
  
--- 589,595 
  			 planstate->instrument->nloops);
  		}
  		else if (es->printAnalyze)
! 			appendStringInfoString(str, " (never executed)");
  	}
  	appendStringInfoChar(str, '\n');
  
***
*** 702,709 
  		List	   *lst;
  
  		for (i = 0; i < indent; i++)
! 			appendStringInfo(str, "  ");
! 		appendStringInfo(str, "  InitPlan\n");
  		foreach(lst, planstate->initPlan)
  		{
  			SubPlanState *sps = (SubPlanState *) lfirst(lst);
--- 702,709 
  		List	   *lst;
  
  		for (i = 0; i < indent; i++)
! 			appendStringInfoString(str, "  ");
! 		appendStringInfoString(str, "  InitPlan\n");
  		foreach(lst, planstate->initPlan)
  		{
  			SubPlanState *sps = (SubPlanState *) lfirst(lst);
***
*** 711,718 
  
  			es->rtable = sp->rtable;
  			for (i = 0; i < indent; i++)
! appendStringInfo(str, "  ");
! 			appendStringInfo(str, "->  ");
  			explain_outNode(str, sp->plan,
  			sps->planstate,
  			NULL,
--- 711,718 
  
  			es->rtable = sp->rtable;
  			for (i = 0; i < indent; i++)
! appendStringInfoString(str, "  ");
! 			appendStringInfoString(str, "->  ");
  			explain_outNode(str, sp->plan,
  			sps->planstate,
  			NULL,
***
*** 725,732 
  	if (outerPlan(plan))
  	{
  		for (i = 0; i < indent; i++)
! 			appendStringInfo(str, "  ");
! 		appendStringInfo(str, "  ->  ");
  		explain_outNode(str, outerPlan(plan),
  		outerPlanState(planstate),
  		NULL,
--- 725,732 
  	if (outerPlan(plan))
  	{
  		for (i = 0; i < indent; i++)
! 			appendStringInfoString(str, "  ");
! 		appendStringInfoString(str, "  ->  ");
  		explain_outNode(str, outerPlan(plan),
  		outerPlanState(planstate),
  		NULL,
***
*** 737,744 
  	if (innerPlan(plan))
  	{
  		for (i = 0; i < indent; i++)
! 			appendStringInfo(str, "  ");
! 		appendStringInfo(str, "  ->  ");
  		explain_outNode(str, innerPlan(plan),
  		innerPlanState(planstate),
  		outerPlan(plan),
--- 737,744 
  	if (innerPlan(plan))
  	{
  		for (i = 0; i < indent; i++)
! 			appendStringInfoString(str, "  ");
! 		appendStringInfoString(str, "  ->  ");
  		explain_outNode(str, innerPlan(plan),
  		innerPlanState(planstate),
  		outerPlan(plan),
***
*** 758,765 
  			Plan	   *subnode = (Plan *) lfirst(lst);
  
  			for (i = 0; i < indent; i++)
! appendStringInfo(str, "  ");
! 			appendStringInfo(str, "  ->  ");
  
  			explain_outNode(str, subnode,
  			appendstate->appendplans[j],
--- 758,765 
  			Plan	   *subnode = (Plan *) lfirst(lst);
  
  			for (i = 0; i < indent; i++)
! appendStringInfoString(str, "  ");
! 			appendStringInfoString(str, "  ->  ");
  
  			explain_outNode(str, subnode,
  			appendstate->appendplans[j],
***
*** 782,789 
  		es->rtable = rte->subquery->rtable;
  
  		for (i = 0; i < indent; i++)
! 			appendStringInfo(str, "  ");
! 		appendStringInfo(str, "  ->  ");
  
  		explain_outNode(str, subnode,
  		subquerystate->subplan,
--- 782,789 
  		es->rtable = rte->subquery->rtable;
  
  		for (i = 0; i < indent; i++)
! 			appendStringInfoString(str, "  ");
! 		appendStringInfoString(str, "  ->  ");
  
  		explain_outNode(str, subnode,
  		subquerystate->subplan,
***
*** 800,807 
  		List	   *lst;
  
  		for (i = 0; i < indent; i++)