Attached is the Freelancer patch so if Andrew and Andrea ould test (and
Andrew look at the code) to see if it is usable, I would appreciate it.
(Andrea, cd to ...cinelerra-5.1/cinelerra   and do "patch < location of
downloaded patch"    should work.

On Mon, Dec 13, 2021 at 12:07 AM Andrew Randrianasulu <
[email protected]> wrote:

>
>
> On Sunday, December 12, 2021, Phyllis Smith <[email protected]>
> wrote:
>
>>
>>
>>> this patch prevent gif segfault problem (but all images become  the same
>>> for given list!) , but not sure about other, similar crashes you observed?
>>>
>> Andrew, patch works just like you stated and most importantly prevents
>> the crash.  Similar mod would have to be put into fileexr.C, filejpeg.C,
>> etc. but let me see if I can get the Freelancer to come up with a different
>> solution -- he keeps nagging me for something to do.
>>
>
> well, I think real solution should augment those filereaders with
> something like report_w, report_h and then caller must check if previous
> (cached) info remain the same for current frame.. so at first call we check
> those params and load them into var1_w, and var1_h, then set someflag
> we_read_first_info, then just copy var1_w/h to var2_w/h, repeat, now when
> we have someflag set (thus not first read) compare those two, abort reading
> of mismatched frame.
>
>
> after trying to write down it like this I even think we can name vars
> first_w, first_h and then check current fetched values against them, not
> re-loading pair for next/priv  frame at each step.
> this is for avoiding  quite expensive decoding, if I understand our code
> correctly!
>
> good luck to freelancer, good health to both of you...
>
>>
>> I agree that it needs a safeguard.  Let me know if you do not find a
>>>> solution because a freelancer wants to work on something and I thought he
>>>> might be able to actually do this.  Most of the problems are way too
>>>> difficult for someone not familiar with Cinelerra to even attempt to work
>>>> on.
>>>>
>>>
>>
>
diff --git a/mnt0/cin5/cinelerra-5.1/cinelerra/filegif.C b/filegif.C
index bb26762..b80f741 100644
--- a/mnt0/cin5/cinelerra-5.1/cinelerra/filegif.C
+++ b/filegif.C
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
+#include <ctype.h>
 
 //from "getarg.h"
 extern "C"
@@ -500,6 +501,65 @@ FrameWriterUnit* FileGIFList::new_writer_unit(FrameWriter *writer)
 	return new GIFUnit(this, writer);
 }
 
+int FileGIFList::verify_file_list()
+{
+ // go through all .gif files in the list and
+ // verify their sizes match or not.
+ //printf("\nAsset Path: %s\n", asset->path);
+ FILE *stream = fopen(asset->path, "rb");
+ if (stream) {
+  char string[BCTEXTLEN];
+  int width, height, prev_width=-1, prev_height=-1;
+  // build the path prefix
+  char prefix[BCTEXTLEN], *bp = prefix, *cp = strrchr(asset->path, '/');
+  for( int i=0, n=!cp ? 0 : cp-asset->path; i<n; ++i ) *bp++ = asset->path[i];
+  *bp = 0;
+  // read entire input file
+  while( !feof(stream) && fgets(string, BCTEXTLEN, stream) ) {
+   int len = strlen(string);
+   if(!len || string[0] == '#' || string[0] == ' ' || isalnum(string[0])) continue;
+   if( string[len-1] == '\n' ) string[len-1] = 0;
+   // a possible .gif file path? fetch it
+   char path[BCTEXTLEN], *pp = path, *ep = pp + sizeof(path)-1;
+   if( string[0] == '.' && string[1] == '/' && prefix[0] )
+    pp += snprintf(pp, ep-pp, "%s/", prefix);
+   snprintf(pp, ep-pp, "%s", string);
+   // check if a valid file exists
+   if(!access(path, R_OK)) {
+    // check file header for size
+    FILE *gif_file_temp = fopen(path, "rb");
+    if (gif_file_temp) {
+     unsigned char test[16];
+     int ret = fread(test, 16, 1, gif_file_temp);
+     fclose(gif_file_temp);
+     if( ret < 1 ) continue;
+     // get height and width of gif file
+     width = test[6] | (test[7] << 8);
+     height = test[8] | (test[9] << 8);
+     // test with previous
+     if ( (prev_width == -1) && (prev_height == -1) ) {
+      prev_width = width;
+      prev_height = height;
+      continue;
+     }
+     else if ( (prev_width != width) || (prev_height != height) ) {
+      // this is the error case we are trying to avoid
+      fclose(stream);
+      return 0;
+     }
+    }
+
+   }
+  }
+  fclose(stream);
+  return 1;
+ }
+ // not sure if our function should be the one to raise not found error
+ perror(asset->path);
+ return 0;
+}
+
+
 GIFUnit::GIFUnit(FileGIFList *file, FrameWriter *writer)
  : FrameWriterUnit(writer)
 {
diff --git a/mnt0/cin5/cinelerra-5.1/cinelerra/filegif.h b/filegif.h
index 74cae2a..98370de 100644
--- a/mnt0/cin5/cinelerra-5.1/cinelerra/filegif.h
+++ b/filegif.h
@@ -80,6 +80,8 @@ public:
 	int use_path() { return 1; }
 	int read_frame(VFrame *output, char *path);
 	int write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit);
+// Need to override this method from FILEBASE class
+ 	int verify_file_list();
 	FrameWriterUnit* new_writer_unit(FrameWriter *writer);
 };
 
diff --git a/mnt0/cin5/cinelerra-5.1/cinelerra/mwindow.C b/mwindow.C
index e4d02d2..a502c15 100644
--- a/mnt0/cin5/cinelerra-5.1/cinelerra/mwindow.C
+++ b/mwindow.C
@@ -2220,6 +2220,13 @@ if(debug) printf("MWindow::load_filenames %d\n", __LINE__);
 			}
 			result = 0;
 			break; }
+// File is a list and size of listed files don't match
+  case FILE_SIZE_DONT_MATCH: {
+   eprintf(_("File sizes don't match"));
+   sprintf(string, _("File sizes don't match"));
+   gui->show_message(string, theme->message_error);
+   gui->update_default_message();
+   break; }
 
 		case FILE_NOT_FOUND: {
 			eprintf(_("Failed to open %s"), new_asset->path);
diff --git a/mnt0/cin5/cinelerra-5.1/cinelerra/filebase.h b/filebase.h
index 3fb8be4..fb10df0 100644
--- a/mnt0/cin5/cinelerra-5.1/cinelerra/filebase.h
+++ b/filebase.h
@@ -132,6 +132,10 @@ public:
 		int channel,
 		int64_t len);
 	void allocate_history(int len);
+// thie function will be used to verify if all files in a given
+// list are of same size or not. Each list type object should 
+// override this method with its own definition.
+        virtual int verify_file_list() { return 1; }
 
 // For static functions to access it
 	Asset *asset;
diff --git a/mnt0/cin5/cinelerra-5.1/cinelerra/file.C b/file.C
index dbcd688..03941d9 100644
--- a/mnt0/cin5/cinelerra-5.1/cinelerra/file.C
+++ b/file.C
@@ -658,6 +658,17 @@ int File::open_file(Preferences *preferences,
 	}
 
 
+// If file type is a list verify that all files match in dimensions.
+// Should be done only after the file open function has been performed
+// Reason: although this function checks if file exists or not but
+// it has no way of relaying this information back and if this function
+// is called before open_file the program may accidently interpret file
+// not found as file size don't match
+ if( !file->verify_file_list() ) {
+  delete file;  file = 0;
+  return FILE_SIZE_DONT_MATCH;
+ }
+
 
 // Set extra writing parameters to mandatory settings.
 	if( wr ) {
diff --git a/mnt0/cin5/cinelerra-5.1/cinelerra/file.inc b/file.inc
index 11a5bc9..c6228a2 100644
--- a/mnt0/cin5/cinelerra-5.1/cinelerra/file.inc
+++ b/file.inc
@@ -53,6 +53,7 @@
 #define FILE_NOT_FOUND 1
 #define FILE_UNRECOGNIZED_CODEC 2
 #define FILE_IS_XML 3
+#define FILE_SIZE_DONT_MATCH 4
 
 // Numeric codes for each file format
 // They're stored in XML files, so they have to be fixed.
-- 
Cin mailing list
[email protected]
https://lists.cinelerra-gg.org/mailman/listinfo/cin

Reply via email to