]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/adouble/ad_open.c
Resource fork offset in adouble header can be after the end of the header, cf.
[netatalk.git] / libatalk / adouble / ad_open.c
index 44aeb5efe2ce0337cd6450a9016d1bc2ea6e33e5..19627794ebf18610ee50861f3ffd586710ec67b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_open.c,v 1.30.6.14 2004-05-11 08:28:33 didg Exp $
+ * $Id: ad_open.c,v 1.30.6.18.2.1 2005-01-25 14:32:00 didg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
@@ -257,6 +257,20 @@ static int ad_update(struct adouble *ad, const char *path)
     LOG(log_debug, logtype_default, "ad_update: file '%s' too big for update.", path);
     goto bail_truncate;
   }
+
+  off = ad->ad_eid[ADEID_RFORK].ade_off;
+  if (off > st.st_size) {
+      LOG(log_error, logtype_default, "ad_v1tov2: invalid resource fork offset. (off: %u)", off); 
+      errno = EIO;
+      goto bail_truncate;
+  }
+
+  if (ad->ad_eid[ADEID_RFORK].ade_len > st.st_size - off) {
+      LOG(log_error, logtype_default, "ad_v1tov2: invalid resource fork length. (rfork len: %u)", ad->ad_eid[ADEID_RFORK].ade_len); 
+      errno = EIO;
+      goto bail_truncate;
+  }
+  
   /* last place for failure. */
   if ((void *) (buf = (char *)
                 mmap(NULL, st.st_size + shiftdata,
@@ -265,7 +279,6 @@ static int ad_update(struct adouble *ad, const char *path)
     goto bail_truncate;
   }
 
-  off = ad->ad_eid[ADEID_RFORK].ade_off;
 
   /* move the RFORK. this assumes that the RFORK is at the end */
   if (off) {
@@ -381,6 +394,20 @@ static int ad_v1tov2(struct adouble *ad, const char *path)
       LOG(log_debug, logtype_default, "ad_v1tov2: file too big."); 
       goto bail_truncate;
   }
+
+  off = ad->ad_eid[ADEID_RFORK].ade_off;
+
+  if (off > st.st_size) {
+      LOG(log_error, logtype_default, "ad_v1tov2: invalid resource fork offset. (off: %u)", off); 
+      errno = EIO;
+      goto bail_truncate;
+  }
+
+  if (ad->ad_eid[ADEID_RFORK].ade_len > st.st_size - off) {
+      LOG(log_error, logtype_default, "ad_v1tov2: invalid resource fork length. (rfork len: %u)", ad->ad_eid[ADEID_RFORK].ade_len); 
+      errno = EIO;
+      goto bail_truncate;
+  }
   
   /* last place for failure. */
   if ((void *) (buf = (char *) 
@@ -390,8 +417,6 @@ static int ad_v1tov2(struct adouble *ad, const char *path)
     goto bail_truncate;
   }
   
-  off = ad->ad_eid[ADEID_RFORK].ade_off;
-
   /* move the RFORK. this assumes that the RFORK is at the end */
   if (off) {
       memmove(buf + ADEDOFF_RFORK_V2, buf + off, ad->ad_eid[ADEID_RFORK].ade_len);
@@ -516,7 +541,8 @@ static void parse_entries(struct adouble *ad, char *buf,
        len = ntohl( len );
        buf += sizeof( len );
 
-       if ( 0 < eid && eid < ADEID_MAX ) {
+       if (eid && eid < ADEID_MAX && ( (off < sizeof(ad->ad_data) && 
+                off +len <= sizeof(ad->ad_data)) || eid == ADEID_RFORK)) {
            ad->ad_eid[ eid ].ade_off = off;
            ad->ad_eid[ eid ].ade_len = len;
        } else if (!warning) {
@@ -1166,8 +1192,8 @@ static int new_rfork(const char *path, struct adouble *ad, int adflags)
                     &ashort, sizeof(ashort));
     } else {
         /* set default creator/type fields */
-       memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,"TEXT", 4);
-       memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,"UNIX", 4);
+       memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,"\0\0\0\0", 4);
+       memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,"\0\0\0\0", 4);
     }
 
     /* make things invisible */