+2025-07-17 Bruno Haible <bruno@clisp.org>
+
+ Fix sb_dupfree(), sbr_dupfree() on an empty buffer.
+ Reported by Marc Nieper-Wißkirchen <marc.nieper+gnu@gmail.com> at
+ <https://lists.gnu.org/archive/html/bug-gnulib/2025-07/msg00119.html>.
+ * lib/string-desc.c (_sd_new_addr, _rwsd_new_addr): Don't canonicalize
+ (0, non-NULL) to (0, NULL).
+ * lib/string-buffer.h (sb_dupfree): Fix description.
+ * lib/string-buffer-reversed.h (sbr_dupfree): Likewise.
+ * tests/test-string-buffer.c (main): Test sb_dupfree on an empty buffer.
+ * tests/test-string-buffer-reversed.c (main): Test sbr_dupfree on an
+ empty buffer.
+
2025-07-16 Collin Funk <collin.funk1@gmail.com>
doc: Use @code around errno constants.
extern const char * sbr_contents_c (struct string_buffer_reversed *buffer);
/* Returns the contents of BUFFER and frees all other memory held by BUFFER.
- Returns NULL upon failure or if there was an error earlier.
+ Returns (0, NULL) upon failure or if there was an error earlier.
It is the responsibility of the caller to sd_free() the result. */
extern rw_string_desc_t sbr_dupfree (struct string_buffer_reversed *buffer)
_GL_ATTRIBUTE_RELEASE_CAPABILITY (buffer->data);
extern const char * sb_contents_c (struct string_buffer *buffer);
/* Returns the contents of BUFFER and frees all other memory held by BUFFER.
- Returns NULL upon failure or if there was an error earlier.
+ Returns (0, NULL) upon failure or if there was an error earlier.
It is the responsibility of the caller to sd_free() the result. */
extern rw_string_desc_t sb_dupfree (struct string_buffer *buffer)
_GL_ATTRIBUTE_RELEASE_CAPABILITY (buffer->data);
string_desc_t result;
result._nbytes = n;
+ /* No, it is not a good idea to canonicalize (0, non-NULL) to (0, NULL).
+ Some functions that return a string_desc_t use a return value of (0, NULL)
+ to denote failure. */
+#if 0
if (n == 0)
result._data = NULL;
else
+#endif
result._data = (char *) addr;
return result;
rw_string_desc_t result;
result._nbytes = n;
+ /* No, it is not a good idea to canonicalize (0, non-NULL) to (0, NULL).
+ Some functions that return a rw_string_desc_t use a return value of
+ (0, NULL) to denote failure. */
+#if 0
if (n == 0)
result._data = NULL;
else
+#endif
result._data = (char *) addr;
return result;
{
struct string_buffer_reversed buffer;
+ sbr_init (&buffer);
+ rw_string_desc_t contents = sbr_dupfree (&buffer);
+ ASSERT (sd_is_empty (contents));
+ /* Here it is important to distinguish (0, NULL), which stands for an error,
+ from (0, non-NULL), which is a successful result. */
+ ASSERT (sd_data (contents) != NULL);
+ sd_free (contents);
+ }
+ {
+ struct string_buffer_reversed buffer;
+
sbr_init (&buffer);
sbr_prepend1 (&buffer, '\377');
sbr_prepend1 (&buffer, 'x');
{
struct string_buffer buffer;
+ sb_init (&buffer);
+ rw_string_desc_t contents = sb_dupfree (&buffer);
+ ASSERT (sd_is_empty (contents));
+ /* Here it is important to distinguish (0, NULL), which stands for an error,
+ from (0, non-NULL), which is a successful result. */
+ ASSERT (sd_data (contents) != NULL);
+ sd_free (contents);
+ }
+ {
+ struct string_buffer buffer;
+
sb_init (&buffer);
sb_append1 (&buffer, 'x');
sb_append1 (&buffer, '\377');