@@ -206,12 +206,12 @@ static void ggml_print_backtrace(void) {
206206void ggml_abort (const char * file , int line , const char * fmt , ...) {
207207 va_list args ;
208208 va_start (args , fmt );
209-
209+
210210 char message [1024 ]; // Adjust size as needed
211211 vsnprintf (message , sizeof (message ), fmt , args );
212-
212+
213213 __android_log_print (ANDROID_LOG_ERROR , "GGML" , "%s:%d: %s" , file , line , message );
214-
214+
215215 va_end (args );
216216
217217 ggml_print_backtrace (); // You may need to modify this function as well
@@ -277,10 +277,10 @@ void ggml_log_internal(enum ggml_log_level level, const char * format, ...) {
277277
278278void ggml_log_callback_default (enum ggml_log_level level , const char * text , void * user_data ) {
279279 (void ) user_data ;
280-
280+
281281 android_LogPriority priority ;
282282 const char * tag = "GGML" ;
283-
283+
284284 // Map GGML log levels to Android log priorities
285285 switch (level ) {
286286 case GGML_LOG_LEVEL_ERROR :
@@ -296,7 +296,7 @@ void ggml_log_callback_default(enum ggml_log_level level, const char * text, voi
296296 priority = ANDROID_LOG_DEBUG ;
297297 break ;
298298 }
299-
299+
300300 __android_log_write (priority , tag , text );
301301}
302302
@@ -601,20 +601,101 @@ FILE * ggml_fopen(const char * fname, const char * mode) {
601601 }
602602
603603 return file ;
604- #else
605- // if file does not have a path, we assume it's a file descriptor
606- if (strchr (fname , '/' ) == NULL ) {
604+ #else // Non-Windows (Android, Linux, etc.)
605+ // Create a mutable copy of fname for parsing
606+ char * fname_copy = strdup (fname );
607+ if (fname_copy == NULL ) {
608+ // Handle memory allocation failure
609+ return NULL ;
610+ }
611+
612+ // Check for ';' separator, which implies "fd;offset" format
613+ char * separator = strchr (fname_copy , ';' );
614+
615+ if (separator != NULL ) {
616+ // Format is "fd;offset"
617+ * separator = '\0' ; // Null-terminate the FD part
618+ char * fd_str = fname_copy ;
619+ char * offset_str = separator + 1 ;
620+
621+ char * endptr_fd ;
622+ long fd_num = strtol (fd_str , & endptr_fd , 10 );
623+
624+ char * endptr_offset ;
625+ long offset_num = 0 ; // Default to 0 if offset part is missing or invalid
626+ if (* offset_str != '\0' ) {
627+ offset_num = strtol (offset_str , & endptr_offset , 10 );
628+ }
629+
630+ // Basic validation for numbers
631+ if ((* endptr_fd != '\0' && * endptr_fd != '\n' && * endptr_fd != '\r' ) ||
632+ (* offset_str != '\0' && * endptr_offset != '\0' && * endptr_offset != '\n' && * endptr_offset != '\r' ))
633+ {
634+ // Parsing error: not pure numbers, or trailing garbage
635+ GGML_LOG_ERROR ("ggml_fopen: Malformed FD string: %s\n" , fname ); // Use your GGML_LOG
636+ free (fname_copy );
637+ return NULL ;
638+ }
639+
640+ int duplicated_fd = dup (fd_num );
641+ if (duplicated_fd < 0 ) {
642+ GGML_LOG_ERROR ("ggml_fopen: dup(%ld) failed: %s\n" , fd_num , strerror (errno ));
643+ free (fname_copy );
644+ return NULL ;
645+ }
646+
647+ if (lseek (duplicated_fd , offset_num , SEEK_SET ) == (off_t )- 1 ) {
648+ GGML_LOG_ERROR ("ggml_fopen: lseek(%d, %ld) failed: %s\n" , duplicated_fd , offset_num , strerror (errno ));
649+ close (duplicated_fd ); // Close duplicated FD on lseek error
650+ free (fname_copy );
651+ return NULL ;
652+ }
653+
654+ FILE * file = fdopen (duplicated_fd , mode );
655+ if (file == NULL ) {
656+ GGML_LOG_ERROR ("ggml_fopen: fdopen(%d) failed: %s\n" , duplicated_fd , strerror (errno ));
657+ close (duplicated_fd ); // Close duplicated FD on fdopen error
658+ }
659+ free (fname_copy ); // Free the duplicated string
660+ return file ;
661+
662+ } else if (strchr (fname , '/' ) == NULL ) {
663+ // Original logic: "fd" as a string (no '/')
664+ // This handles where it's only an integer (no seek)
607665 char * endptr ;
608666 long num = strtol (fname , & endptr , 10 );
609- FILE * file = fdopen (dup (num ), mode );
610667
611- if (file != NULL ) {
612- return file ;
613- }
668+ // Validate that the entire string was a number
669+ if (* endptr != '\0' && * endptr != '\n' && * endptr != '\r' ) {
670+ GGML_LOG_ERROR ("ggml_fopen: Malformed FD string (no slash): %s\n" , fname );
671+ free (fname_copy );
672+ return NULL ;
673+ }
674+
675+ int duplicated_fd = dup (num );
676+ if (duplicated_fd < 0 ) {
677+ GGML_LOG_ERROR ("ggml_fopen: dup(%ld) failed: %s\n" , num , strerror (errno ));
678+ free (fname_copy );
679+ return NULL ;
680+ }
681+
682+ FILE * file = fdopen (duplicated_fd , mode );
683+ if (file == NULL ) {
684+ GGML_LOG_ERROR ("ggml_fopen: fdopen(%d) failed: %s\n" , duplicated_fd , strerror (errno ));
685+ close (duplicated_fd ); // Close duplicated FD on fdopen error
686+ }
687+ free (fname_copy ); // Free the duplicated string
688+ return file ;
689+ } else {
690+ // It's a regular file path (contains '/')
691+ FILE * file = fopen (fname , mode );
692+ if (file == NULL ) {
693+ GGML_LOG_ERROR ("ggml_fopen: fopen(%s) failed: %s\n" , fname , strerror (errno ));
694+ }
695+ free (fname_copy ); // Free the duplicated string
696+ return file ;
614697 }
615- return fopen (fname , mode );
616698#endif
617-
618699}
619700static void ggml_vec_dot_f32 (int n , float * GGML_RESTRICT s , size_t bs , const float * GGML_RESTRICT x , size_t bx , const float * GGML_RESTRICT y , size_t by , int nrc );
620701static void ggml_vec_dot_f16 (int n , float * GGML_RESTRICT s , size_t bs , ggml_fp16_t * GGML_RESTRICT x , size_t bx , ggml_fp16_t * GGML_RESTRICT y , size_t by , int nrc );
0 commit comments