From 804f882e3862307d374b53482bab1a884051fa12 Mon Sep 17 00:00:00 2001
From: Tsuda Kageyu <tsuda.kageyu@gmail.com>
Date: Tue, 11 Jun 2013 12:06:29 +0900
Subject: [PATCH 1/2] Uses ISO _strdup() instead of POSIX strdup() if possible

---
 ConfigureChecks.cmake | 10 +++++++++
 bindings/c/tag_c.cpp  | 51 +++++++++++++++++++++++++++++++------------
 config.h.cmake        |  3 +++
 3 files changed, 50 insertions(+), 14 deletions(-)

diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 672005aa..3fd5c687 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -238,6 +238,16 @@ if(NOT HAVE_SNPRINTF)
   " HAVE_SPRINTF_S)
 endif()
 
+# Check which your compiler supports ISO _strdup.
+
+check_cxx_source_compiles("
+  #include <cstring>
+  int main() { 
+    _strdup(0); 
+    return 0; 
+}
+" HAVE_ISO_STRDUP)
+
 # Determine whether your compiler supports codecvt.
 
 check_cxx_source_compiles("
diff --git a/bindings/c/tag_c.cpp b/bindings/c/tag_c.cpp
index e5436cea..816b9578 100644
--- a/bindings/c/tag_c.cpp
+++ b/bindings/c/tag_c.cpp
@@ -19,7 +19,7 @@
  *   USA                                                                   *
  ***************************************************************************/
 
-#include "taglib_config.h"
+#include "config.h"
 #include <stdlib.h>
 #include <fileref.h>
 #include <tfile.h>
@@ -41,9 +41,32 @@
 
 using namespace TagLib;
 
-static List<char *> strings;
-static bool unicodeStrings = true;
-static bool stringManagementEnabled = true;
+namespace
+{
+  List<char *> strings;
+  bool unicodeStrings = true;
+  bool stringManagementEnabled = true;
+
+  inline char *stringToCharArray(const String &s)
+  {
+    const char *c = s.toCString(unicodeStrings);
+
+#ifdef HAVE_ISO_STRDUP
+
+    return ::_strdup(c);
+
+#else
+
+    return ::strdup(c);
+
+#endif
+  }
+
+  inline String charArrayToString(const char *s)
+  {
+    return String(s, unicodeStrings ? String::UTF8 : String::Latin1);
+  }
+}
 
 void taglib_set_strings_unicode(BOOL unicode)
 {
@@ -133,7 +156,7 @@ BOOL taglib_file_save(TagLib_File *file)
 char *taglib_tag_title(const TagLib_Tag *tag)
 {
   const Tag *t = reinterpret_cast<const Tag *>(tag);
-  char *s = ::strdup(t->title().toCString(unicodeStrings));
+  char *s = stringToCharArray(t->title());
   if(stringManagementEnabled)
     strings.append(s);
   return s;
@@ -142,7 +165,7 @@ char *taglib_tag_title(const TagLib_Tag *tag)
 char *taglib_tag_artist(const TagLib_Tag *tag)
 {
   const Tag *t = reinterpret_cast<const Tag *>(tag);
-  char *s = ::strdup(t->artist().toCString(unicodeStrings));
+  char *s = stringToCharArray(t->artist());
   if(stringManagementEnabled)
     strings.append(s);
   return s;
@@ -151,7 +174,7 @@ char *taglib_tag_artist(const TagLib_Tag *tag)
 char *taglib_tag_album(const TagLib_Tag *tag)
 {
   const Tag *t = reinterpret_cast<const Tag *>(tag);
-  char *s = ::strdup(t->album().toCString(unicodeStrings));
+  char *s = stringToCharArray(t->album());
   if(stringManagementEnabled)
     strings.append(s);
   return s;
@@ -160,7 +183,7 @@ char *taglib_tag_album(const TagLib_Tag *tag)
 char *taglib_tag_comment(const TagLib_Tag *tag)
 {
   const Tag *t = reinterpret_cast<const Tag *>(tag);
-  char *s = ::strdup(t->comment().toCString(unicodeStrings));
+  char *s = stringToCharArray(t->comment());
   if(stringManagementEnabled)
     strings.append(s);
   return s;
@@ -169,7 +192,7 @@ char *taglib_tag_comment(const TagLib_Tag *tag)
 char *taglib_tag_genre(const TagLib_Tag *tag)
 {
   const Tag *t = reinterpret_cast<const Tag *>(tag);
-  char *s = ::strdup(t->genre().toCString(unicodeStrings));
+  char *s = stringToCharArray(t->genre());
   if(stringManagementEnabled)
     strings.append(s);
   return s;
@@ -190,31 +213,31 @@ unsigned int taglib_tag_track(const TagLib_Tag *tag)
 void taglib_tag_set_title(TagLib_Tag *tag, const char *title)
 {
   Tag *t = reinterpret_cast<Tag *>(tag);
-  t->setTitle(String(title, unicodeStrings ? String::UTF8 : String::Latin1));
+  t->setTitle(charArrayToString(title));
 }
 
 void taglib_tag_set_artist(TagLib_Tag *tag, const char *artist)
 {
   Tag *t = reinterpret_cast<Tag *>(tag);
-  t->setArtist(String(artist, unicodeStrings ? String::UTF8 : String::Latin1));
+  t->setArtist(charArrayToString(artist));
 }
 
 void taglib_tag_set_album(TagLib_Tag *tag, const char *album)
 {
   Tag *t = reinterpret_cast<Tag *>(tag);
-  t->setAlbum(String(album, unicodeStrings ? String::UTF8 : String::Latin1));
+  t->setAlbum(charArrayToString(album));
 }
 
 void taglib_tag_set_comment(TagLib_Tag *tag, const char *comment)
 {
   Tag *t = reinterpret_cast<Tag *>(tag);
-  t->setComment(String(comment, unicodeStrings ? String::UTF8 : String::Latin1));
+  t->setComment(charArrayToString(comment));
 }
 
 void taglib_tag_set_genre(TagLib_Tag *tag, const char *genre)
 {
   Tag *t = reinterpret_cast<Tag *>(tag);
-  t->setGenre(String(genre, unicodeStrings ? String::UTF8 : String::Latin1));
+  t->setGenre(charArrayToString(genre));
 }
 
 void taglib_tag_set_year(TagLib_Tag *tag, unsigned int year)
diff --git a/config.h.cmake b/config.h.cmake
index 086122c6..b182589e 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -39,6 +39,9 @@
 #cmakedefine   HAVE_SNPRINTF 1
 #cmakedefine   HAVE_SPRINTF_S 1
 
+/* Defined if your compiler supports ISO _strdup. */
+#cmakedefine   HAVE_ISO_STRDUP 1
+
 /* Defined if your compiler supports codecvt */
 #cmakedefine   HAVE_STD_CODECVT 1
 

From c9904354f963a54cce9cce3661d3e3ee965f8e05 Mon Sep 17 00:00:00 2001
From: Tsuda Kageyu <tsuda.kageyu@gmail.com>
Date: Tue, 11 Jun 2013 12:51:26 +0900
Subject: [PATCH 2/2] Prevent string conversion buffer to stay in memory

---
 bindings/c/tag_c.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/bindings/c/tag_c.cpp b/bindings/c/tag_c.cpp
index 816b9578..007ab823 100644
--- a/bindings/c/tag_c.cpp
+++ b/bindings/c/tag_c.cpp
@@ -49,15 +49,15 @@ namespace
 
   inline char *stringToCharArray(const String &s)
   {
-    const char *c = s.toCString(unicodeStrings);
+    const std::string str = s.to8Bit(unicodeStrings);
 
 #ifdef HAVE_ISO_STRDUP
 
-    return ::_strdup(c);
+    return ::_strdup(str.c_str());
 
 #else
 
-    return ::strdup(c);
+    return ::strdup(str.c_str());
 
 #endif
   }