From: "Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: gitster@pobox.com, peff@peff.net, newren@gmail.com,
Derrick Stolee <stolee@gmail.com>,
Derrick Stolee <stolee@gmail.com>
Subject: [PATCH 6/6] strbuf-safe: add init and release methods
Date: Fri, 18 Sep 2026 13:02:20 +0000 [thread overview]
Message-ID: <dea925f31647e7c08f3fa467b8058351b463f593.1789736540.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2230.git.1789736540.gitgitgadget@gmail.com>
From: Derrick Stolee <stolee@gmail.com>
Continue extending the strbuf-safe API by adding these safe versions of the
initialize and release methods:
* sstrbuf_init()
* sstrbuf_release()
These both depend on sstrbuf_grow() that was introduced in the previous
change.
As we are working to make json-writer.c a safe API, adapt its use of
strbuf_release() to the safe version. To properly handle the responses of
the safe versions, some methods are converted to return their own error
codes. However, callers of those methods are not adapted at this time and
will be adapted in future changes. This leaves a window where json-writer
consumers may continue running after an error occurs, potentially leading to
a different error in the future.
Signed-off-by: Derrick Stolee <stolee@gmail.com>
---
json-writer.c | 31 +++++++++++++++++++------------
json-writer.h | 5 +++--
strbuf-safe.c | 18 ++++++++++++++++++
strbuf-safe.h | 2 ++
strbuf.c | 12 ++++--------
5 files changed, 46 insertions(+), 22 deletions(-)
diff --git a/json-writer.c b/json-writer.c
index e7fc5775da..38351f3439 100644
--- a/json-writer.c
+++ b/json-writer.c
@@ -3,6 +3,8 @@
#include "git-compat-util.h"
#include "json-writer.h"
#include "strbuf.h"
+/* banned-die must be last. */
+#include "banned-die.h"
void jw_init(struct json_writer *jw)
{
@@ -10,10 +12,15 @@ void jw_init(struct json_writer *jw)
memcpy(jw, &blank, sizeof(*jw));;
}
-void jw_release(struct json_writer *jw)
+int jw_release(struct json_writer *jw)
{
- strbuf_release(&jw->json);
- strbuf_release(&jw->open_stack);
+ enum safe_result result = SUCCESS;
+
+ /* attempt both removals without short-circuiting. */
+ result = sstrbuf_release(&jw->json) || result;
+ result = sstrbuf_release(&jw->open_stack) || result;
+
+ return result;
}
/*
@@ -99,16 +106,17 @@ static void maybe_add_comma(struct json_writer *jw)
jw->need_comma = 1;
}
-static void fmt_double(struct json_writer *jw, int precision,
- double value)
+static int fmt_double(struct json_writer *jw, int precision,
+ double value)
{
if (precision < 0) {
strbuf_addf(&jw->json, "%f", value);
+ return 0;
} else {
struct strbuf fmt = STRBUF_INIT;
strbuf_addf(&fmt, "%%.%df", precision);
strbuf_addf(&jw->json, fmt.buf, value);
- strbuf_release(&fmt);
+ return sstrbuf_release(&fmt);
}
}
@@ -235,8 +243,8 @@ static void kill_indent(struct strbuf *sb,
}
}
-static void append_sub_jw(struct json_writer *jw,
- const struct json_writer *value)
+static int append_sub_jw(struct json_writer *jw,
+ const struct json_writer *value)
{
/*
* If both are pretty, increase the indentation of the sub_jw
@@ -255,18 +263,17 @@ static void append_sub_jw(struct json_writer *jw,
struct strbuf sb = STRBUF_INIT;
increase_indent(&sb, value, jw->open_stack.len * 2);
strbuf_addbuf(&jw->json, &sb);
- strbuf_release(&sb);
- return;
+ return sstrbuf_release(&sb);
}
if (!jw->pretty && value->pretty) {
struct strbuf sb = STRBUF_INIT;
kill_indent(&sb, value);
strbuf_addbuf(&jw->json, &sb);
- strbuf_release(&sb);
- return;
+ return sstrbuf_release(&sb);
}
strbuf_addbuf(&jw->json, &value->json);
+ return 0;
}
void jw_object_sub_jw(struct json_writer *jw, const char *key,
diff --git a/json-writer.h b/json-writer.h
index fa8cf02253..72277d9839 100644
--- a/json-writer.h
+++ b/json-writer.h
@@ -103,9 +103,10 @@ struct json_writer
void jw_init(struct json_writer *jw);
/*
- * Release the internal buffers of a json_writer.
+ * Release the internal buffers of a json_writer. Returns nonzero on
+ * failure.
*/
-void jw_release(struct json_writer *jw);
+int jw_release(struct json_writer *jw);
/*
* Begin the json_writer using an object as the top-level data structure. If
diff --git a/strbuf-safe.c b/strbuf-safe.c
index e4a0707d63..7a8701e827 100644
--- a/strbuf-safe.c
+++ b/strbuf-safe.c
@@ -32,3 +32,21 @@ enum safe_result sstrbuf_grow(struct strbuf *sb, size_t extra)
return SUCCESS;
}
+
+enum safe_result sstrbuf_init(struct strbuf *sb, size_t hint)
+{
+ struct strbuf blank = STRBUF_INIT;
+ memcpy(sb, &blank, sizeof(*sb));
+ if (!hint)
+ return 0;
+ return sstrbuf_grow(sb, hint);
+}
+
+enum safe_result sstrbuf_release(struct strbuf *sb)
+{
+ if (sb->alloc) {
+ free(sb->buf);
+ return sstrbuf_init(sb, 0);
+ }
+ return 0;
+}
diff --git a/strbuf-safe.h b/strbuf-safe.h
index f6adf7434b..fe04d9cf62 100644
--- a/strbuf-safe.h
+++ b/strbuf-safe.h
@@ -91,5 +91,7 @@ enum safe_result {
};
enum safe_result sstrbuf_grow(struct strbuf *sb, size_t extra);
+enum safe_result sstrbuf_init(struct strbuf *sb, size_t hint);
+enum safe_result sstrbuf_release(struct strbuf *sb);
#endif /* STRBUF_SAFE_H */
diff --git a/strbuf.c b/strbuf.c
index d005666a07..835238dc64 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -70,18 +70,14 @@ char strbuf_slopbuf[1];
void strbuf_init(struct strbuf *sb, size_t hint)
{
- struct strbuf blank = STRBUF_INIT;
- memcpy(sb, &blank, sizeof(*sb));
- if (hint)
- strbuf_grow(sb, hint);
+ if (sstrbuf_init(sb, hint))
+ STRBUF_DIE("strbuf_init");
}
void strbuf_release(struct strbuf *sb)
{
- if (sb->alloc) {
- free(sb->buf);
- strbuf_init(sb, 0);
- }
+ if (sstrbuf_release(sb))
+ STRBUF_DIE("strbuf_release");
}
char *strbuf_detach(struct strbuf *sb, size_t *sz)
--
gitgitgadget
next prev parent reply other threads:[~2026-09-18 13:02 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 13:02 [PATCH 0/6] [RFC] Create a 'safe' strbuf API Derrick Stolee via GitGitGadget
2026-09-18 13:02 ` [PATCH 1/6] strbuf: add header for 'safe' API Derrick Stolee via GitGitGadget
2026-09-21 21:18 ` Junio C Hamano
2026-09-23 19:25 ` Mark C. Chu-Carroll
2026-09-23 20:14 ` Junio C Hamano
2026-09-18 13:02 ` [PATCH 2/6] wrapper: initialize GIT_ALLOC_LIMIT proactively Derrick Stolee via GitGitGadget
2026-09-18 13:02 ` [PATCH 3/6] wrapper: create safe_memory_limit_check() Derrick Stolee via GitGitGadget
2026-09-21 21:24 ` Junio C Hamano
2026-09-18 13:02 ` [PATCH 4/6] strbuf-safe: add sstrbuf_grow() Derrick Stolee via GitGitGadget
2026-09-21 21:29 ` Junio C Hamano
2026-09-18 13:02 ` [PATCH 5/6] json-writer: include strbuf-safe.h Derrick Stolee via GitGitGadget
2026-09-18 13:02 ` Derrick Stolee via GitGitGadget [this message]
2026-09-21 21:44 ` [PATCH 6/6] strbuf-safe: add init and release methods Junio C Hamano
2026-09-21 22:34 ` Junio C Hamano
2026-09-19 15:23 ` [PATCH 0/6] [RFC] Create a 'safe' strbuf API Phillip Wood
2026-09-23 19:46 ` Jeff King
2026-10-06 14:33 ` Derrick Stolee
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=dea925f31647e7c08f3fa467b8058351b463f593.1789736540.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=newren@gmail.com \
--cc=peff@peff.net \
--cc=stolee@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox