From 0fc8a0e69f2028566aee1484305487d6108b638e Mon Sep 17 00:00:00 2001
From: Tsuda Kageyu <tsuda.kageyu@gmail.com>
Date: Mon, 4 Aug 2014 23:45:59 +0900
Subject: [PATCH] Workaround for 64-bit MP4 atoms.

---
 ConfigureChecks.cmake  | 51 +++++++++++++++++++++++-------------------
 config.h.cmake         |  3 +++
 taglib/mp4/mp4atom.cpp | 14 +++++++++---
 3 files changed, 42 insertions(+), 26 deletions(-)

diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 23830f93..12bbed2c 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -20,6 +20,11 @@ if(NOT ${SIZEOF_INT} EQUAL 4)
   MESSAGE(FATAL_ERROR "TagLib requires that int is 32-bit wide.")
 endif()
 
+check_type_size("long" SIZEOF_LONG)
+if(${SIZEOF_LONG} EQUAL 8)
+  set(LONG_IS_INT64 1)
+endif()
+
 check_type_size("long long" SIZEOF_LONGLONG)
 if(NOT ${SIZEOF_LONGLONG} EQUAL 8)
   MESSAGE(FATAL_ERROR "TagLib requires that long long is 64-bit wide.")
@@ -66,65 +71,65 @@ endif()
 
 check_cxx_source_compiles("
   #include <atomic>
-  int main() { 
+  int main() {
     std::atomic<unsigned int> x;
     x.fetch_add(1);
     x.fetch_sub(1);
-    return 0; 
+    return 0;
   }
 " HAVE_STD_ATOMIC)
 
 if(NOT HAVE_STD_ATOMIC)
   check_cxx_source_compiles("
     #include <boost/atomic.hpp>
-    int main() { 
+    int main() {
       boost::atomic<unsigned int> x(1);
       x.fetch_add(1);
       x.fetch_sub(1);
-      return 0; 
+      return 0;
     }
   " HAVE_BOOST_ATOMIC)
 
   if(NOT HAVE_BOOST_ATOMIC)
     check_cxx_source_compiles("
-      int main() { 
+      int main() {
         volatile int x;
         __sync_add_and_fetch(&x, 1);
         int y = __sync_sub_and_fetch(&x, 1);
-        return 0; 
+        return 0;
       }
     " HAVE_GCC_ATOMIC)
 
     if(NOT HAVE_GCC_ATOMIC)
       check_cxx_source_compiles("
         #include <libkern/OSAtomic.h>
-        int main() { 
+        int main() {
           volatile int32_t x;
           OSAtomicIncrement32Barrier(&x);
           int32_t y = OSAtomicDecrement32Barrier(&x);
-          return 0; 
+          return 0;
         }
       " HAVE_MAC_ATOMIC)
 
       if(NOT HAVE_MAC_ATOMIC)
         check_cxx_source_compiles("
           #include <windows.h>
-          int main() { 
+          int main() {
             volatile LONG x;
             InterlockedIncrement(&x);
             LONG y = InterlockedDecrement(&x);
-            return 0; 
+            return 0;
           }
         " HAVE_WIN_ATOMIC)
 
         if(NOT HAVE_WIN_ATOMIC)
           check_cxx_source_compiles("
             #include <ia64intrin.h>
-            int main() { 
+            int main() {
               volatile int x;
               __sync_add_and_fetch(&x, 1);
               int y = __sync_sub_and_fetch(&x, 1);
-              return 0; 
+              return 0;
             }
           " HAVE_IA64_ATOMIC)
         endif()
@@ -135,26 +140,26 @@ endif()
 
 # Determine which kind of byte swap functions your compiler supports.
 
-# GCC's __builtin_bswap* should be checked individually 
+# GCC's __builtin_bswap* should be checked individually
 # because some of them can be missing depends on the GCC version.
 check_cxx_source_compiles("
   int main() {
     __builtin_bswap16(0);
-    return 0; 
+    return 0;
   }
 " HAVE_GCC_BYTESWAP_16)
 
 check_cxx_source_compiles("
   int main() {
     __builtin_bswap32(0);
-    return 0; 
+    return 0;
   }
 " HAVE_GCC_BYTESWAP_32)
 
 check_cxx_source_compiles("
   int main() {
     __builtin_bswap64(0);
-    return 0; 
+    return 0;
   }
 " HAVE_GCC_BYTESWAP_64)
 
@@ -165,7 +170,7 @@ if(NOT HAVE_GCC_BYTESWAP_16 OR NOT HAVE_GCC_BYTESWAP_32 OR NOT HAVE_GCC_BYTESWAP
       __bswap_16(0);
       __bswap_32(0);
       __bswap_64(0);
-      return 0; 
+      return 0;
     }
   " HAVE_GLIBC_BYTESWAP)
 
@@ -176,7 +181,7 @@ if(NOT HAVE_GCC_BYTESWAP_16 OR NOT HAVE_GCC_BYTESWAP_32 OR NOT HAVE_GCC_BYTESWAP
         _byteswap_ushort(0);
         _byteswap_ulong(0);
         _byteswap_uint64(0);
-        return 0; 
+        return 0;
       }
     " HAVE_MSC_BYTESWAP)
 
@@ -187,7 +192,7 @@ if(NOT HAVE_GCC_BYTESWAP_16 OR NOT HAVE_GCC_BYTESWAP_32 OR NOT HAVE_GCC_BYTESWAP
           OSSwapInt16(0);
           OSSwapInt32(0);
           OSSwapInt64(0);
-          return 0; 
+          return 0;
         }
       " HAVE_MAC_BYTESWAP)
 
@@ -198,7 +203,7 @@ if(NOT HAVE_GCC_BYTESWAP_16 OR NOT HAVE_GCC_BYTESWAP_32 OR NOT HAVE_GCC_BYTESWAP
             swap16(0);
             swap32(0);
             swap64(0);
-            return 0; 
+            return 0;
           }
         " HAVE_OPENBSD_BYTESWAP)
       endif()
@@ -224,9 +229,9 @@ endif()
 
 check_cxx_source_compiles("
   #include <codecvt>
-  int main() { 
-    std::codecvt_utf8_utf16<wchar_t> x; 
-    return 0; 
+  int main() {
+    std::codecvt_utf8_utf16<wchar_t> x;
+    return 0;
   }
 " HAVE_STD_CODECVT)
 
diff --git a/config.h.cmake b/config.h.cmake
index 07abffa6..abecfbfb 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -8,6 +8,9 @@
 /* 1 if little-endian, 2 if big-endian. */
 #cmakedefine   FLOAT_BYTEORDER  ${FLOAT_BYTEORDER}
 
+/* Defined if long is 64-bit wide */
+#cmakedefine   LONG_IS_INT64    ${LONG_IS_INT64}
+
 /* Defined if your compiler supports some byte swap functions */
 #cmakedefine   HAVE_GCC_BYTESWAP_16 1
 #cmakedefine   HAVE_GCC_BYTESWAP_32 1
diff --git a/taglib/mp4/mp4atom.cpp b/taglib/mp4/mp4atom.cpp
index 7b87a479..5a304e3f 100644
--- a/taglib/mp4/mp4atom.cpp
+++ b/taglib/mp4/mp4atom.cpp
@@ -23,6 +23,10 @@
  *   http://www.mozilla.org/MPL/                                           *
  ***************************************************************************/
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <tdebug.h>
 #include <tstring.h>
 #include "mp4atom.h"
@@ -50,9 +54,12 @@ MP4::Atom::Atom(File *file)
 
   length = header.toUInt();
 
-  if (length == 1) {
+  if(length == 1) {
     const long long longLength = file->readBlock(8).toLongLong();
-    if (longLength >= 8 && longLength <= 0xFFFFFFFF) {
+#ifdef LONG_IS_INT64
+    length = longLength;
+#else
+    if(longLength <= 0xFFFFFFFF) {
         // The atom has a 64-bit length, but it's actually a 32-bit value
         length = (long)longLength;
     }
@@ -62,8 +69,9 @@ MP4::Atom::Atom(File *file)
         file->seek(0, File::End);
         return;
     }
+#endif
   }
-  if (length < 8) {
+  if(length < 8) {
     debug("MP4: Invalid atom size");
     length = 0;
     file->seek(0, File::End);