GNU bug report logs - #77840
Testing diffutils 3.12 on PPC Mac OS X 10.4.11, Tiger, produces so many failures

Previous Next

Package: diffutils;

Reported by: Peter Dyballa <Peter_Dyballa <at> Web.DE>

Date: Wed, 16 Apr 2025 10:55:02 UTC

Severity: normal

Full log


View this message in rfc822 format

From: Peter Dyballa <Peter_Dyballa <at> Web.DE>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 77840 <at> debbugs.gnu.org
Subject: bug#77840: [bug-diffutils] bug#77840: Testing diffutils 3.12 on PPC Mac OS X 10.4.11, Tiger, produces so many failures
Date: Fri, 20 Jun 2025 12:01:56 +0200
In diff.c:882 we have in main():

	exit_status = compare_files (&noparent, de_unknowns, argv[optind], argv[optind + 1]);.

This function is defined in diff.c, starting at lines #1376 (comments) or #1387 (code). It has close to its end on line #1633/1634:

	  if (status == EXIT_SUCCESS)
	    status = compare_prepped_files (parent, &cmp, O_RDONLY | oflags);

compare_prepped_files() is new, compared to diffutils 3.10, and is also defined in diff.c, lines #1158 (comments) or #1162 (code). It has at its end on line #1372:

	  return diff_2_files (cmp);

This function is defined in analyze.c, starting at lines #451 (comments) or #452 (code). It has inside a switch statement

  621	              switch (output_style)
  622	                {
  623	                case OUTPUT_CONTEXT:
  624	                  print_context_script (script, false);
  625	                  break;
  626	
  627	                case OUTPUT_UNIFIED:
  628	                  print_context_script (script, true);
  629	                  break;

So it's the print_context_script() branch of function calls that contains the faulty code. It's defined in context.c, starting at lines #109 (comments) or #111 (code). It makes a comparison between context and unified diff:

  123	  if (unidiff)
  124	    print_script (script, find_hunk, pr_unidiff_hunk);
  125	  else
  126	    print_script (script, find_hunk, pr_context_hunk);

The array script was created before, it is created in (almost?) any case:

	context.c:124:    print_script (script, find_hunk, pr_unidiff_hunk);
	context.c:126:    print_script (script, find_hunk, pr_context_hunk);
	ed.c:33:  print_script (script, find_change, print_ed_hunk);
	ed.c:97:  print_script (script, find_change, pr_forward_ed_hunk);
	ed.c:136:  print_script (script, find_change, print_rcs_hunk);
	ifdef.c:54:  print_script (script, find_change, print_ifdef_hunk);
	normal.c:31:  print_script (script, find_change, print_normal_hunk);
	side.c:41:  print_script (script, find_change, print_sdiff_hunk);

The function print_script() is defined in util.c, starting at lines #941 (comments) or #952 (code), find_hunk() and find_change() are functions (find_change() is defined in util.c, find_hunk() is defined in context.c) and presumingly OK (although I could see contradicting line numbers in output?). The third argument of print_script() varies a bit in name (pr_ vs. print_), they are defined in different files, each working on a particular diff case (ed script, "normal", side-by-side, and context/unified). So it's possible that pr_unidiff_hunk and pr_context_hunk can have the faulty code, twice?

find_hunk() has only one argument (struct change *script), works on its contents and returns the finished struct. Rather negligible:

  429	/* Scan a (forward-ordered) edit script for the first place that more than
  430	   2*CONTEXT unchanged lines appear, and return a pointer
  431	   to the 'struct change' for the last change before those lines.  */
  432	
  433	static struct change * ATTRIBUTE_PURE
  434	find_hunk (struct change *script)
  435	{
  436	  /* Threshold distance is CONTEXT if the second change is ignorable,
  437	     min (2 * CONTEXT + 1, LIN_MAX) otherwise.  */
  438	  lin ignorable_threshold = context;
  439	  lin non_ignorable_threshold = (ckd_mul (&non_ignorable_threshold, context, 2)
  440					 ? LIN_MAX
  441					 : non_ignorable_threshold + 1);
  442	
  443	  for (struct change *next; ; script = next)
  444	    {
  445	      next = script->link;
  446	      /* Compute number of first line in each file beyond this changed.  */
  447	      lin top0 = script->line0 + script->deleted;
  448	      lin top1 = script->line1 + script->inserted;
  449	      lin thresh = (next && next->ignore
  450			    ? ignorable_threshold
  451			    : non_ignorable_threshold);
  452	      /* It is not supposed to matter which file we check in the end-test.  */
  453	      dassert (!next || next->line0 - top0 == next->line1 - top1);
  454	
  455	      /* Keep going if less than THRESH lines elapse
  456		 before the affected line.  */
  457	      if (!next || thresh <= next->line0 - top0)
  458		return script;
  459	    }
  460	}

pr_context_hunk()/pr_unidiff_hunk() make internal use of the curr struct, change its contents, obviously not a file name or such. Instead they call begin_output() – a function that is also used in the other diff cases… But it has a special clause near its end:

	  886	  /* A special header is needed at the beginning of context output.  */
	  887	  if (output_style == OUTPUT_CONTEXT || output_style == OUTPUT_UNIFIED)
	  888	    print_context_header (curr.file, names,
	  889				  output_style == OUTPUT_UNIFIED);

Only in our two faulty cases, unified and context diff, the malfunction happens. So 'print_context_header()' must contain the bug, but it's too simple, in context.c:

	   92	/* Print a header for a context diff, with the file names and dates.  */
	   93	
	   94	void
	   95	print_context_header (struct file_data inf[], char const *const *names, bool unidiff)
	   96	{
	   97	  if (unidiff)
	   98	    {
	   99	      print_context_label ("---", &inf[0], names[0], file_label[0]);
	  100	      print_context_label ("+++", &inf[1], names[1], file_label[1]);
	  101	    }
	  102	  else
	  103	    {
	  104	      print_context_label ("***", &inf[0], names[0], file_label[0]);
	  105	      print_context_label ("---", &inf[1], names[1], file_label[1]);
	  106	    }
	  107	}

This function has the declaration 'char const *const *names', but definition of 'print_context_label()' starts with:

	   40	static void
	   41	print_context_label (char const *mark,
	   42	                     struct file_data *inf,
	   43	                     char const *name,
	   44	                     char const *label)
	   45	{

To me "char const *const *" is not the same as "char const *" – could be for PPC Mac OS X 10.4.11 too? I do not understand these code differences anyway.


Comparing the function definition in both versions 3.12 and 3.10 I see that time is handled differently – cause found? In the end both functions simply have:

	  set_color_context (RESET_CONTEXT);
	  putc ('\n', outfile);

The newer version has

     24      int nsec = ts.tv_nsec;

On Tiger /usr/include/time.h has:

     87 #ifndef _TIMESPEC                 88 #define _TIMESPEC
     89 struct timespec {
     90         time_t  tv_sec;         /* seconds */
     91         long    tv_nsec;        /* and nanoseconds */
     92 };
     93 #endif
     94
     95 struct tm {
     96         int     tm_sec;         /* seconds after the minute [0-60] */
     97         int     tm_min;         /* minutes after the hour [0-59] */
     98         int     tm_hour;        /* hours since midnight [0-23] */
     99         int     tm_mday;        /* day of the month [1-31] */
    100         int     tm_mon;         /* months since January [0-11] */
    101         int     tm_year;        /* years since 1900 */
    102         int     tm_wday;        /* days since Sunday [0-6] */
    103         int     tm_yday;        /* days since January 1 [0-365] */
    104         int     tm_isdst;       /* Daylight Savings Time flag */
    105         long    tm_gmtoff;      /* offset from CUT in seconds */
    106         char    *tm_zone;       /* timezone abbreviation */
    107 };


nstrftime() is not known on Tiger, but defined in lib/strftime.h. I'll check that area, either (much) later or tomorrow!

--
Greetings

  Pete

We also sponsor National Invisible Chronic Illness Awareness Week annually in September.
Join the millions!





This bug report was last modified 92 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.