<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>sprintf() and size restrictions</title>
		<link>http://www.allegro.cc/forums/view/595278</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Wed, 27 Feb 2008 10:27:08 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I have a small char array (let&#39;s say 10 bytes) that I want to pass into sprintf().  What happens if sprintf() pushes too much onto that array?  Here&#39;s an example of how to reproduce this:
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="p">#include &lt;iostream&gt;</span></td></tr><tr><td class="number">2</td><td>&#160;</td></tr><tr><td class="number">3</td><td><span class="k1">int</span> main<span class="k2">(</span><span class="k2">)</span></td></tr><tr><td class="number">4</td><td><span class="k2">{</span></td></tr><tr><td class="number">5</td><td>  <span class="k1">int</span> a <span class="k3">=</span> <span class="n">1234</span><span class="k2">;</span></td></tr><tr><td class="number">6</td><td>  <span class="k1">char</span> buffer<span class="k2">[</span><span class="n">10</span><span class="k2">]</span> <span class="k3">=</span> <span class="k2">{</span><span class="n">0</span><span class="k2">}</span><span class="k2">;</span></td></tr><tr><td class="number">7</td><td>&#160;</td></tr><tr><td class="number">8</td><td>  <span class="c">// This should be "10"</span></td></tr><tr><td class="number">9</td><td>  std::cerr <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="s">"The size of buffer is: "</span> <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="k1">sizeof</span><span class="k2">(</span>buffer<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">10</td><td>&#160;</td></tr><tr><td class="number">11</td><td>  <span class="c">// This should be "0"</span></td></tr><tr><td class="number">12</td><td>  std::cerr <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="s">", and the string length of buffer: "</span> <span class="k3">&lt;</span><span class="k3">&lt;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_764.html" target="_blank">strlen</a><span class="k2">(</span>buffer<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">13</td><td>  std::cerr <span class="k3">&lt;</span><span class="k3">&lt;</span> std::endl<span class="k2">;</span></td></tr><tr><td class="number">14</td><td>&#160;</td></tr><tr><td class="number">15</td><td>  <span class="c">// stuff buffer[] with more than 10 chars</span></td></tr><tr><td class="number">16</td><td>  <a href="http://www.delorie.com/djgpp/doc/libc/libc_737.html" target="_blank">sprintf</a><span class="k2">(</span>buffer, <span class="s">"I will stuff 'buffer' with lots of text and numbers (like %d)!\n"</span>, a<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">17</td><td>&#160;</td></tr><tr><td class="number">18</td><td>  <span class="c">// This should still be "10"</span></td></tr><tr><td class="number">19</td><td>  std::cerr <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="s">"Now the size of buffer is: "</span> <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="k1">sizeof</span><span class="k2">(</span>buffer<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">20</td><td>&#160;</td></tr><tr><td class="number">21</td><td>  <span class="c">// This results in "65"</span></td></tr><tr><td class="number">22</td><td>  std::cerr <span class="k3">&lt;</span><span class="k3">&lt;</span> <span class="s">", and the string length of buffer is: "</span> <span class="k3">&lt;</span><span class="k3">&lt;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_764.html" target="_blank">strlen</a><span class="k2">(</span>buffer<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">23</td><td>  std::cerr <span class="k3">&lt;</span><span class="k3">&lt;</span> std::endl<span class="k2">;</span></td></tr><tr><td class="number">24</td><td>&#160;</td></tr><tr><td class="number">25</td><td>  <span class="k1">return</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">26</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>

This will crash with a SEGFAULT (so if you run it, do it through a debugger).  Apparently, sprintf() is unsafe and &quot;keeps going until it&#39;s done&quot; but doesn&#39;t do any bounds checking.</p><p>Is there a &quot;safe&quot; sprintf() function, like sprint<u><b>n</b></u>f() that I can use to ensure that I don&#39;t exceed a specified size?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (OnlineCop)</author>
		<pubDate>Wed, 27 Feb 2008 08:19:22 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Apparently, sprintf() is unsafe and &quot;keeps going until it&#39;s done&quot; but doesn&#39;t do any bounds checking.
</p></div></div><p>
Of course, because you don&#39;t tell it how big its bounds are (it&#39;s not psychic).</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Is there a &quot;safe&quot; sprintf() function, like sprintnf() that I can use to ensure that I don&#39;t exceed a specified size?
</p></div></div><p>
<span class="source-code"><a href="http://www.delorie.com/djgpp/doc/libc/libc_732.html" target="_blank">snprintf</a></span><br />Or using that <i>other</i> OS that doesn&#39;t like to play by everyone else&#39;s standards: <tt>_snprintf</tt> or <tt>sprintf_s</tt>.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kitty Cat)</author>
		<pubDate>Wed, 27 Feb 2008 08:32:49 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Perfect.  Thanks, KC!
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (OnlineCop)</author>
		<pubDate>Wed, 27 Feb 2008 09:11:08 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I personally like using the return value of snprintf, and passing NULL to the string arg so it just calculates the total length, and then allocating a properly sized buffer to do it again.</p><p>Another option is to use GCC&#39;s asprintf. It allocates the buffer for you.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Thomas Fjellstrom)</author>
		<pubDate>Wed, 27 Feb 2008 09:22:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Uhh... you&#39;re using iostream and sprintf? Why???</p><p>Use #include &lt;strstream&gt;
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Goalie Ca)</author>
		<pubDate>Wed, 27 Feb 2008 09:59:07 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Thomas Fjellstrom said:</div><div class="quote"><p>
I personally like using the return value of snprintf, and passing NULL to the string arg so it just calculates the total length, and then allocating a properly sized buffer to do it again.
</p></div></div><p>
O_o
</p><div class="source-code snippet"><div class="inner"><pre>    <span class="k1">char</span><span class="k3">*</span> buf <span class="k3">=</span> NULL<span class="k2">;</span>
    <span class="k1">int</span> len <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span>

    len <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_732.html" target="_blank">snprintf</a><span class="k2">(</span>buf, <span class="n">0</span>, <span class="s">"foo"</span><span class="k2">)</span><span class="k2">;</span>
    buf <span class="k3">=</span> <span class="k2">(</span><span class="k1">char</span><span class="k3">*</span><span class="k2">)</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_551.html" target="_blank">malloc</a><span class="k2">(</span>len<span class="k3">+</span><span class="n">1</span><span class="k2">)</span><span class="k2">;</span>
    len <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_732.html" target="_blank">snprintf</a><span class="k2">(</span>buf, len, <span class="s">"foo"</span><span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>
<img src="http://www.allegro.cc/forums/smileys/huh.gif" alt="???" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (bamccaig)</author>
		<pubDate>Wed, 27 Feb 2008 10:01:33 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="source-code snippet"><div class="inner"><pre>    <span class="k1">char</span><span class="k3">*</span> buf <span class="k3">=</span> NULL<span class="k2">;</span>
    <span class="k1">int</span> len <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span>

    len <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_732.html" target="_blank">snprintf</a><span class="k2">(</span>buf, <span class="n">0</span>, <span class="s">"foo"</span><span class="k2">)</span><span class="k2">;</span>
    buf <span class="k3">=</span> <span class="k2">(</span><span class="k1">char</span><span class="k3">*</span><span class="k2">)</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_551.html" target="_blank">malloc</a><span class="k2">(</span>len<span class="k2">)</span><span class="k2">;</span>
    len <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_732.html" target="_blank">snprintf</a><span class="k2">(</span>buf, len, <span class="s">"foo"</span><span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>pretty much, though I&#39;d do it like so:</p><div class="source-code snippet"><div class="inner"><pre>    <span class="k1">char</span><span class="k3">*</span> buf <span class="k3">=</span> NULL<span class="k2">;</span>
    <span class="k1">int</span> len <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span>

    len <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_732.html" target="_blank">snprintf</a><span class="k2">(</span>NULL, <span class="n">0</span>, <span class="s">"foo"</span><span class="k2">)</span><span class="k2">;</span>
    buf <span class="k3">=</span> <span class="k2">(</span><span class="k1">char</span><span class="k3">*</span><span class="k2">)</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_551.html" target="_blank">malloc</a><span class="k2">(</span>len<span class="k3">+</span><span class="n">1</span><span class="k2">)</span><span class="k2">;</span>
    <a href="http://www.delorie.com/djgpp/doc/libc/libc_732.html" target="_blank">snprintf</a><span class="k2">(</span>buf, len, <span class="s">"foo"</span><span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>

Just to be obvious about the NULL bit.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Thomas Fjellstrom)</author>
		<pubDate>Wed, 27 Feb 2008 10:16:04 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Stringstream = better.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (BAF)</author>
		<pubDate>Wed, 27 Feb 2008 10:19:17 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Is there a sprintf()-style function available for std::string?  If so, you wouldn&#39;t need to worry about memory allocation/deallocation or string length.</p><p>Does <tt>std::stringstream</tt> allow you to do this?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (OnlineCop)</author>
		<pubDate>Wed, 27 Feb 2008 10:21:56 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Stringstream = better.
</p></div></div><p>

Though you get problems trying to use it in C. <img src="http://www.allegro.cc/forums/smileys/wink.gif" alt=";)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (LennyLen)</author>
		<pubDate>Wed, 27 Feb 2008 10:21:57 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>OnlineCop: yes.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (BAF)</author>
		<pubDate>Wed, 27 Feb 2008 10:27:08 +0000</pubDate>
	</item>
</rss>
