<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 267: interaction of strstreambuf::overflow() and seekoff()</title>
<meta property="og:title" content="Issue 267: interaction of strstreambuf::overflow() and seekoff()">
<meta property="og:description" content="C++ library issue. Status: NAD">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue267.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#NAD">NAD</a> status.</em></p>
<h3 id="267"><a href="lwg-closed.html#267">267</a>. interaction of strstreambuf::overflow() and seekoff()</h3>
<p><b>Section:</b> 99 [depr.strstreambuf.virtuals] <b>Status:</b> <a href="lwg-active.html#NAD">NAD</a>
 <b>Submitter:</b> Martin Sebor <b>Opened:</b> 2000-10-05 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#depr.strstreambuf.virtuals">issues</a> in [depr.strstreambuf.virtuals].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD">NAD</a> status.</p>
<p><b>Discussion:</b></p>
<p>
It appears that the interaction of the strstreambuf members overflow()
and seekoff() can lead to undefined behavior in cases where defined
behavior could reasonably be expected. The following program
demonstrates this behavior:
</p>

<pre>
    #include &lt;strstream&gt;

    int main ()
    {
         std::strstreambuf sb;
         sb.sputc ('c');

         sb.pubseekoff (-1, std::ios::end, std::ios::in);
         return !('c' == sb.sgetc ());
    }
</pre>

<p>
D.7.1.1, p1 initializes strstreambuf with a call to basic_streambuf&lt;&gt;(),
which in turn sets all pointers to 0 in 27.5.2.1, p1.
</p>
 
<p>
27.5.2.2.5, p1 says that basic_streambuf&lt;&gt;::sputc(c) calls
overflow(traits::to_int_type(c)) if a write position isn't available (it
isn't due to the above).
</p>

<p>
D.7.1.3, p3 says that strstreambuf::overflow(off, ..., ios::in) makes at
least one write position available (i.e., it allows the function to make
any positive number of write positions available).
</p>

<p>
D.7.1.3, p13 computes newoff = seekhigh - eback(). In D.7.1, p4 we see
seekhigh = epptr() ? epptr() : egptr(), or seekhigh = epptr() in this
case. newoff is then epptr() - eback().
</p>

<p>
D.7.1.4, p14 sets gptr() so that gptr() == eback() + newoff + off, or
gptr() == epptr() + off holds.
</p>

<p>
If strstreambuf::overflow() made exactly one write position available
then gptr() will be set to just before epptr(), and the program will
return 0. Buf if the function made more than one write position
available, epptr() and gptr() will both point past pptr() and the
behavior of the program is undefined.
</p>


<p id="res-267"><b>Proposed resolution:</b></p>


   <p>Change the last sentence of 99 [depr.strstreambuf] paragraph 4 from</p>

      <blockquote><p>
      Otherwise, seeklow equals gbeg and seekhigh is either pend, if
      pend is not a null pointer, or gend.
      </p></blockquote>

   <p>to become</p>

      <blockquote><p>
      Otherwise, seeklow equals gbeg and seekhigh is either gend if
      0 == pptr(), or pbase() + max where max is the maximum value of
      pptr() - pbase() ever reached for this stream.
      </p></blockquote>

<p><i>[
  pre-Copenhagen: Dietmar provided wording for proposed resolution.
]</i></p>


<p><i>[
  post-Copenhagen: Fixed a typo: proposed resolution said to fix
  4.7.1, not D.7.1.
]</i></p>




<p><b>Rationale:</b></p>
<p>This is related to issue <a href="lwg-closed.html#65" title="Underspecification of strstreambuf::seekoff (Status: NAD)">65</a><sup><a href="https://cplusplus.github.io/LWG/issue65" title="Latest snapshot">(i)</a></sup>: it's not clear what it
means to seek beyond the current area.  Without resolving issue <a href="lwg-closed.html#65" title="Underspecification of strstreambuf::seekoff (Status: NAD)">65</a><sup><a href="https://cplusplus.github.io/LWG/issue65" title="Latest snapshot">(i)</a></sup> we can't resolve this.  As with issue <a href="lwg-closed.html#65" title="Underspecification of strstreambuf::seekoff (Status: NAD)">65</a><sup><a href="https://cplusplus.github.io/LWG/issue65" title="Latest snapshot">(i)</a></sup>, 
the library working group does not wish to invest time nailing down
corner cases in a deprecated feature.</p>





</body>
</html>
