git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/3] diff.c: remove unnecessary typecast
       [not found] <1456145545-5374-1-git-send-email-pclouds@gmail.com>
@ 2016-02-22 12:52 ` Nguyễn Thái Ngọc Duy
  2016-02-22 12:52 ` [PATCH 3/3] Correct conditions to free textconv result data Nguyễn Thái Ngọc Duy
  1 sibling, 0 replies; 10+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2016-02-22 12:52 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 diff.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/diff.c b/diff.c
index 8b3a3db..5bdc3c0 100644
--- a/diff.c
+++ b/diff.c
@@ -717,8 +717,8 @@ static void emit_rewrite_diff(const char *name_a,
 	ecbdata.opt = o;
 	if (ecbdata.ws_rule & WS_BLANK_AT_EOF) {
 		mmfile_t mf1, mf2;
-		mf1.ptr = (char *)data_one;
-		mf2.ptr = (char *)data_two;
+		mf1.ptr = data_one;
+		mf2.ptr = data_two;
 		mf1.size = size_one;
 		mf2.size = size_two;
 		check_blank_at_eof(&mf1, &mf2, &ecbdata);
-- 
2.7.1.532.gd9e3aaa

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] Correct conditions to free textconv result data
       [not found] <1456145545-5374-1-git-send-email-pclouds@gmail.com>
  2016-02-22 12:52 ` [PATCH 2/3] diff.c: remove unnecessary typecast Nguyễn Thái Ngọc Duy
@ 2016-02-22 12:52 ` Nguyễn Thái Ngọc Duy
  2016-02-22 13:00   ` Duy Nguyen
  2016-02-22 18:06   ` Jeff King
  1 sibling, 2 replies; 10+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2016-02-22 12:52 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

fill_textconv() have four code paths to return a new buffer. Two of
them, run_textconv() and notes_cache_get(), return a newly allocated
buffer. The other two return either a constant string or an existing
buffer (mmfile_t). We can only free the result buffer if it's allocated
by fill_textconv(). Correct all call sites.

Changes in combine-diff.c are not clear from diff output. We need to
force not running fill_textconv() unless the function returns a new
buffer so that it falls to the "else" case and allocates a new buffer
with no conversion.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Frankly I don't like the way fill_textconv() returns buffer at all.
 But I don't know much about textconv, or want to spend more time on
 it. This patch can be dropped if people come up with a better one.

 builtin/blame.c    | 2 +-
 combine-diff.c     | 4 ++--
 diff.c             | 8 ++++----
 diffcore-pickaxe.c | 5 +++--
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/builtin/blame.c b/builtin/blame.c
index cb6f2fb..b5477ad 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -166,7 +166,7 @@ int textconv_object(const char *path,
 	df = alloc_filespec(path);
 	fill_filespec(df, sha1, sha1_valid, mode);
 	textconv = get_textconv(df);
-	if (!textconv) {
+	if (!textconv || !textconv->textconv) {
 		free_filespec(df);
 		return 0;
 	}
diff --git a/combine-diff.c b/combine-diff.c
index 5571304..c57cefd 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -299,7 +299,7 @@ static char *grab_blob(const struct object_id *oid, unsigned int mode,
 		/* deleted blob */
 		*size = 0;
 		return xcalloc(1, 1);
-	} else if (textconv) {
+	} else if (textconv && textconv->textconv) {
 		struct diff_filespec *df = alloc_filespec(path);
 		fill_filespec(df, oid->hash, 1, mode);
 		*size = fill_textconv(textconv, df, &blob);
@@ -1022,7 +1022,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
 			else
 				result = grab_blob(&oid, elem->mode,
 						   &result_size, NULL, NULL);
-		} else if (textconv) {
+		} else if (textconv && textconv->textconv) {
 			struct diff_filespec *df = alloc_filespec(elem->path);
 			fill_filespec(df, null_sha1, 0, st.st_mode);
 			result_size = fill_textconv(textconv, df, &result);
diff --git a/diff.c b/diff.c
index 5bdc3c0..173ec5b 100644
--- a/diff.c
+++ b/diff.c
@@ -744,9 +744,9 @@ static void emit_rewrite_diff(const char *name_a,
 		emit_rewrite_lines(&ecbdata, '-', data_one, size_one);
 	if (lc_b)
 		emit_rewrite_lines(&ecbdata, '+', data_two, size_two);
-	if (textconv_one)
+	if (textconv_one && textconv_one->textconv)
 		free((char *)data_one);
-	if (textconv_two)
+	if (textconv_two && textconv_two->textconv)
 		free((char *)data_two);
 }
 
@@ -2454,9 +2454,9 @@ static void builtin_diff(const char *name_a,
 			die("unable to generate diff for %s", one->path);
 		if (o->word_diff)
 			free_diff_words_data(&ecbdata);
-		if (textconv_one)
+		if (textconv_one && textconv_one->textconv)
 			free(mf1.ptr);
-		if (textconv_two)
+		if (textconv_two && textconv_two->textconv)
 			free(mf2.ptr);
 		xdiff_clear_find_func(&xecfg);
 	}
diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
index 7715c13..f89e106 100644
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c
@@ -7,6 +7,7 @@
 #include "diffcore.h"
 #include "xdiff-interface.h"
 #include "kwset.h"
+#include "userdiff.h"
 
 typedef int (*pickaxe_fn)(mmfile_t *one, mmfile_t *two,
 			  struct diff_options *o,
@@ -150,9 +151,9 @@ static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
 		 DIFF_FILE_VALID(p->two) ? &mf2 : NULL,
 		 o, regexp, kws);
 
-	if (textconv_one)
+	if (textconv_one && textconv_one->textconv)
 		free(mf1.ptr);
-	if (textconv_two)
+	if (textconv_two && textconv_two->textconv)
 		free(mf2.ptr);
 	diff_free_filespec_data(p->one);
 	diff_free_filespec_data(p->two);
-- 
2.7.1.532.gd9e3aaa

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] Correct conditions to free textconv result data
  2016-02-22 12:52 ` [PATCH 3/3] Correct conditions to free textconv result data Nguyễn Thái Ngọc Duy
@ 2016-02-22 13:00   ` Duy Nguyen
  2016-02-22 18:06   ` Jeff King
  1 sibling, 0 replies; 10+ messages in thread
From: Duy Nguyen @ 2016-02-22 13:00 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Nguyễn Thái Ngọc Duy

On Mon, Feb 22, 2016 at 7:52 PM, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:
> fill_textconv() have four code paths to return a new buffer.

I forgot to add. Thanks to -Wwrite-strings pointing to '*outbuf = ""'
line in this function. I wouldn't notice otherwise.
-- 
Duy

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] Correct conditions to free textconv result data
  2016-02-22 12:52 ` [PATCH 3/3] Correct conditions to free textconv result data Nguyễn Thái Ngọc Duy
  2016-02-22 13:00   ` Duy Nguyen
@ 2016-02-22 18:06   ` Jeff King
  2016-02-22 18:12     ` Jeff King
  2016-02-22 18:28     ` [PATCH] diff: clarify textconv interface Jeff King
  1 sibling, 2 replies; 10+ messages in thread
From: Jeff King @ 2016-02-22 18:06 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

On Mon, Feb 22, 2016 at 07:52:25PM +0700, Nguyễn Thái Ngọc Duy wrote:

> fill_textconv() have four code paths to return a new buffer. Two of
> them, run_textconv() and notes_cache_get(), return a newly allocated
> buffer. The other two return either a constant string or an existing
> buffer (mmfile_t). We can only free the result buffer if it's allocated
> by fill_textconv(). Correct all call sites.

Right, and those two cases (allocated or not) should follow based on
whether you passed in a textconv-enabled driver.

> diff --git a/builtin/blame.c b/builtin/blame.c
> index cb6f2fb..b5477ad 100644
> --- a/builtin/blame.c
> +++ b/builtin/blame.c
> @@ -166,7 +166,7 @@ int textconv_object(const char *path,
>  	df = alloc_filespec(path);
>  	fill_filespec(df, sha1, sha1_valid, mode);
>  	textconv = get_textconv(df);
> -	if (!textconv) {
> +	if (!textconv || !textconv->textconv) {
>  		free_filespec(df);
>  		return 0;
>  	}

This change (and the other similar ones) doesn't make any sense to me.
The point of get_textconv() is to return the userdiff driver if and only
if it has textconv enabled.

I have a feeling you were confused by the fact that fill_textconv()
does:

  if (!driver || !driver->textconv)

to decide whether to allocate the textconv buffer. The latter half of
that is really just defensive programming, and I think this would
probably be better as:

  if (driver)
	....

  assert(driver->textconv);

to make it more clear that we assume the parameter came from
get_textconv().

And if there's a case that triggers that assert(), then I think the bug
is in the caller, which should be fixed.

Is there a case I'm missing here where we actually leak memory or try to
free non-allocated memory? I didn't see it.

-Peff

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] Correct conditions to free textconv result data
  2016-02-22 18:06   ` Jeff King
@ 2016-02-22 18:12     ` Jeff King
  2016-02-22 23:03       ` Duy Nguyen
  2016-02-22 18:28     ` [PATCH] diff: clarify textconv interface Jeff King
  1 sibling, 1 reply; 10+ messages in thread
From: Jeff King @ 2016-02-22 18:12 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

On Mon, Feb 22, 2016 at 01:06:46PM -0500, Jeff King wrote:

> Is there a case I'm missing here where we actually leak memory or try to
> free non-allocated memory? I didn't see it.

By the way, I saw only patches 2/3 and 3/3 on the list. So maybe there
is something interesting going on in 1/3, or in a cover letter that
didn't make it. :)

-Peff

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] diff: clarify textconv interface
  2016-02-22 18:06   ` Jeff King
  2016-02-22 18:12     ` Jeff King
@ 2016-02-22 18:28     ` Jeff King
  2016-02-22 23:01       ` Duy Nguyen
  1 sibling, 1 reply; 10+ messages in thread
From: Jeff King @ 2016-02-22 18:28 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

On Mon, Feb 22, 2016 at 01:06:45PM -0500, Jeff King wrote:

> I have a feeling you were confused by the fact that fill_textconv()
> does:

Looking over it, I agree this is a pretty confusing interface that grew
out of control over time.  But refactoring it is kind of tricky, because
we really do want to avoid extra allocations, or cross-module
assumptions (e.g., userdiff doesn't know about diff_filespec, but rather
the other way around, and we probably do not want to muck with the
internals of a diff_filespec when doing a textconv).

So I think the patch below is an improvement, but if somebody really
wants to dig into refactoring it, be my guest.

-- >8 --
Subject: [PATCH] diff: clarify textconv interface

The memory allocation scheme for the textconv interface is a
bit tricky, and not well documented. It was originally
designed as an internal part of diff.c (matching
fill_mmfile), but gradually was made public.

Refactoring it is difficult, but we can at least improve the
situation by documenting the intended flow and enforcing it
with an in-code assertion.

Signed-off-by: Jeff King <peff@peff.net>
---
 diff.c     |  5 ++++-
 diff.h     | 16 ++++++++++++++++
 userdiff.h |  4 ++++
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/diff.c b/diff.c
index 2136b69..a088e26 100644
--- a/diff.c
+++ b/diff.c
@@ -5085,7 +5085,7 @@ size_t fill_textconv(struct userdiff_driver *driver,
 {
 	size_t size;
 
-	if (!driver || !driver->textconv) {
+	if (!driver) {
 		if (!DIFF_FILE_VALID(df)) {
 			*outbuf = "";
 			return 0;
@@ -5096,6 +5096,9 @@ size_t fill_textconv(struct userdiff_driver *driver,
 		return df->size;
 	}
 
+	if (!driver->textconv)
+		die("BUG: fill_textconv called with non-textconv driver");
+
 	if (driver->textconv_cache && df->sha1_valid) {
 		*outbuf = notes_cache_get(driver->textconv_cache, df->sha1,
 					  &size);
diff --git a/diff.h b/diff.h
index 70b2d70..4505b4d 100644
--- a/diff.h
+++ b/diff.h
@@ -349,10 +349,26 @@ extern void diff_no_index(struct rev_info *, int, const char **);
 
 extern int index_differs_from(const char *def, int diff_flags);
 
+/*
+ * Fill the contents of the filespec "df", respecting any textconv defined by
+ * its userdiff driver.  The "driver" parameter must come from a
+ * previous call to get_textconv(), and therefore should either be NULL or have
+ * textconv enabled.
+ *
+ * Note that the memory ownership of the resulting buffer depends on whether
+ * the driver field is NULL. If it is, then the memory belongs to the filespec
+ * struct. If it is non-NULL, then "outbuf" points to a newly allocated buffer
+ * that should be freed by the caller.
+ */
 extern size_t fill_textconv(struct userdiff_driver *driver,
 			    struct diff_filespec *df,
 			    char **outbuf);
 
+/*
+ * Look up the userdiff driver for the given filespec, and return it if
+ * and only if it has textconv enabled (otherwise return NULL). The result
+ * can be passed to fill_textconv().
+ */
 extern struct userdiff_driver *get_textconv(struct diff_filespec *one);
 
 extern int parse_rename_score(const char **cp_p);
diff --git a/userdiff.h b/userdiff.h
index 4a7e78f..2ef0ce5 100644
--- a/userdiff.h
+++ b/userdiff.h
@@ -23,6 +23,10 @@ int userdiff_config(const char *k, const char *v);
 struct userdiff_driver *userdiff_find_by_name(const char *name);
 struct userdiff_driver *userdiff_find_by_path(const char *path);
 
+/*
+ * Initialize any textconv-related fields in the driver and return it, or NULL
+ * if it does not have textconv enabled at all.
+ */
 struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver);
 
 #endif /* USERDIFF */
-- 
2.7.1.652.g2fdcad6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] diff: clarify textconv interface
  2016-02-22 18:28     ` [PATCH] diff: clarify textconv interface Jeff King
@ 2016-02-22 23:01       ` Duy Nguyen
  0 siblings, 0 replies; 10+ messages in thread
From: Duy Nguyen @ 2016-02-22 23:01 UTC (permalink / raw)
  To: Jeff King; +Cc: Git Mailing List

On Tue, Feb 23, 2016 at 1:28 AM, Jeff King <peff@peff.net> wrote:
> On Mon, Feb 22, 2016 at 01:06:45PM -0500, Jeff King wrote:
>
>> I have a feeling you were confused by the fact that fill_textconv()
>> does:
>
> Looking over it, I agree this is a pretty confusing interface that grew
> out of control over time.  But refactoring it is kind of tricky, because
> we really do want to avoid extra allocations, or cross-module
> assumptions (e.g., userdiff doesn't know about diff_filespec, but rather
> the other way around, and we probably do not want to muck with the
> internals of a diff_filespec when doing a textconv).
>
> So I think the patch below is an improvement, but if somebody really
> wants to dig into refactoring it, be my guest.

I almost went this way but I wasn't sure if driver->textconv can be
NULL on purpose. Definitely an improvement.
-- 
Duy

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] Correct conditions to free textconv result data
  2016-02-22 18:12     ` Jeff King
@ 2016-02-22 23:03       ` Duy Nguyen
  2016-02-22 23:08         ` Junio C Hamano
  0 siblings, 1 reply; 10+ messages in thread
From: Duy Nguyen @ 2016-02-22 23:03 UTC (permalink / raw)
  To: Jeff King; +Cc: Git Mailing List

On Tue, Feb 23, 2016 at 1:12 AM, Jeff King <peff@peff.net> wrote:
> On Mon, Feb 22, 2016 at 01:06:46PM -0500, Jeff King wrote:
>
>> Is there a case I'm missing here where we actually leak memory or try to
>> free non-allocated memory? I didn't see it.
>
> By the way, I saw only patches 2/3 and 3/3 on the list. So maybe there
> is something interesting going on in 1/3, or in a cover letter that
> didn't make it. :)

The only thing common in this series is it's the result of
-Wwrite-strings. 1/3 changes some "char *" to "const char *", you
don't miss anything.
-- 
Duy

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] Correct conditions to free textconv result data
  2016-02-22 23:03       ` Duy Nguyen
@ 2016-02-22 23:08         ` Junio C Hamano
  2016-02-22 23:25           ` Jeff King
  0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2016-02-22 23:08 UTC (permalink / raw)
  To: Duy Nguyen; +Cc: Jeff King, Git Mailing List

Duy Nguyen <pclouds@gmail.com> writes:

> On Tue, Feb 23, 2016 at 1:12 AM, Jeff King <peff@peff.net> wrote:
>> On Mon, Feb 22, 2016 at 01:06:46PM -0500, Jeff King wrote:
>>
>>> Is there a case I'm missing here where we actually leak memory or try to
>>> free non-allocated memory? I didn't see it.
>>
>> By the way, I saw only patches 2/3 and 3/3 on the list. So maybe there
>> is something interesting going on in 1/3, or in a cover letter that
>> didn't make it. :)
>
> The only thing common in this series is it's the result of
> -Wwrite-strings. 1/3 changes some "char *" to "const char *", you
> don't miss anything.

While reading Peff's clarification patch, I did find the assignment
of "" to the *out pointer disturbing.  That part of your patch (I
presume that is what you mean by the above) may want to be revived.

Thanks.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] Correct conditions to free textconv result data
  2016-02-22 23:08         ` Junio C Hamano
@ 2016-02-22 23:25           ` Jeff King
  0 siblings, 0 replies; 10+ messages in thread
From: Jeff King @ 2016-02-22 23:25 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Duy Nguyen, Git Mailing List

On Mon, Feb 22, 2016 at 03:08:01PM -0800, Junio C Hamano wrote:

> > The only thing common in this series is it's the result of
> > -Wwrite-strings. 1/3 changes some "char *" to "const char *", you
> > don't miss anything.
> 
> While reading Peff's clarification patch, I did find the assignment
> of "" to the *out pointer disturbing.  That part of your patch (I
> presume that is what you mean by the above) may want to be revived.

That part was inherited from diff_populate_filespec, though it casts
explicitly to "char *" since d2543b8 (Clean up diff.c, 2006-06-24).
I guess we could do the same here (not that it makes things any safer,
but at least tells everyone "yes, I _know_ this is weird".

-Peff

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2016-02-22 23:25 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1456145545-5374-1-git-send-email-pclouds@gmail.com>
2016-02-22 12:52 ` [PATCH 2/3] diff.c: remove unnecessary typecast Nguyễn Thái Ngọc Duy
2016-02-22 12:52 ` [PATCH 3/3] Correct conditions to free textconv result data Nguyễn Thái Ngọc Duy
2016-02-22 13:00   ` Duy Nguyen
2016-02-22 18:06   ` Jeff King
2016-02-22 18:12     ` Jeff King
2016-02-22 23:03       ` Duy Nguyen
2016-02-22 23:08         ` Junio C Hamano
2016-02-22 23:25           ` Jeff King
2016-02-22 18:28     ` [PATCH] diff: clarify textconv interface Jeff King
2016-02-22 23:01       ` Duy Nguyen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).