Replace broken str* functions with safe versions.
diff --git a/src/flac/encode.c b/src/flac/encode.c
index c3e470c..50ca006 100644
--- a/src/flac/encode.c
+++ b/src/flac/encode.c
@@ -32,6 +32,7 @@
 #include "share/grabbag.h"
 #include "share/compat.h"
 #include "share/private.h"
+#include "share/safe_str.h"
 #include "encode.h"
 
 #ifdef min
@@ -2070,8 +2071,8 @@
 					return false;
 				}
 				else {
-					strcat(apodizations, options.compression_settings[ic].value.t_string);
-					strcat(apodizations, ";");
+					safe_strncat(apodizations, options.compression_settings[ic].value.t_string, sizeof(apodizations));
+					safe_strncat(apodizations, ";", sizeof(apodizations));
 				}
 				break;
 			case CST_MAX_LPC_ORDER:
diff --git a/src/flac/main.c b/src/flac/main.c
index 3880d09..5e4879f 100644
--- a/src/flac/main.c
+++ b/src/flac/main.c
@@ -37,6 +37,7 @@
 #include "share/alloc.h"
 #include "share/grabbag.h"
 #include "share/compat.h"
+#include "share/safe_str.h"
 #include "analyze.h"
 #include "decode.h"
 #include "encode.h"
@@ -977,8 +978,8 @@
 						return usage_error("ERROR: too many seekpoints requested\n");
 					}
 					else {
-						strcat(option_values.requested_seek_points, option_argument);
-						strcat(option_values.requested_seek_points, ";");
+						safe_strncat(option_values.requested_seek_points, option_argument, sizeof(option_values.requested_seek_points));
+						safe_strncat(option_values.requested_seek_points, ";", sizeof(option_values.requested_seek_points));
 					}
 				}
 				break;
@@ -1894,14 +1895,15 @@
 	/* if infilename and outfilename point to the same file, we need to write to a temporary file */
 	if(encode_infile != stdin && grabbag__file_are_same(infilename, outfilename)) {
 		static const char *tmp_suffix = ".tmp,fl-ac+en'c";
+		size_t dest_len = strlen(outfilename) + strlen(tmp_suffix) + 1;
 		/*@@@@ still a remote possibility that a file with this filename exists */
-		if(0 == (internal_outfilename = safe_malloc_add_3op_(strlen(outfilename), /*+*/strlen(tmp_suffix), /*+*/1))) {
+		if(0 == (internal_outfilename = safe_malloc_(dest_len))) {
 			flac__utils_printf(stderr, 1, "ERROR allocating memory for tempfile name\n");
 			conditional_fclose(encode_infile);
 			return 1;
 		}
-		strcpy(internal_outfilename, outfilename);
-		strcat(internal_outfilename, tmp_suffix);
+		safe_strncpy(internal_outfilename, outfilename, dest_len);
+		safe_strncat(internal_outfilename, tmp_suffix, dest_len);
 	}
 
 	if(input_format == FORMAT_RAW) {
@@ -2173,7 +2175,7 @@
 		static char buffer[4096]; /* @@@ bad MAGIC NUMBER */
 
 		if(0 == strcmp(infilename, "-") || option_values.force_to_stdout) {
-			strcpy(buffer, "-");
+			safe_strncpy(buffer, "-", sizeof(buffer));
 		}
 		else {
 			char *p;
diff --git a/src/libFLAC/metadata_iterators.c b/src/libFLAC/metadata_iterators.c
index d2a229a..bc3823e 100644
--- a/src/libFLAC/metadata_iterators.c
+++ b/src/libFLAC/metadata_iterators.c
@@ -47,6 +47,7 @@
 #include "share/alloc.h"
 #include "share/compat.h"
 #include "share/macros.h"
+#include "share/safe_str.h"
 #include "private/macros.h"
 #include "private/memory.h"
 
@@ -3198,28 +3199,32 @@
 {
 	static const char *tempfile_suffix = ".metadata_edit";
 	if(0 == tempfile_path_prefix) {
-		if(0 == (*tempfilename = safe_malloc_add_3op_(strlen(filename), /*+*/strlen(tempfile_suffix), /*+*/1))) {
+		size_t dest_len = strlen(filename) + strlen(tempfile_suffix) + 1;
+		if(0 == (*tempfilename = safe_malloc_(dest_len))) {
 			*status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
 			return false;
 		}
-		strcpy(*tempfilename, filename);
-		strcat(*tempfilename, tempfile_suffix);
+		safe_strncpy(*tempfilename, filename, dest_len);
+		safe_strncat(*tempfilename, tempfile_suffix, dest_len);
 	}
 	else {
 		const char *p = strrchr(filename, '/');
+		size_t dest_len;
 		if(0 == p)
 			p = filename;
 		else
 			p++;
 
-		if(0 == (*tempfilename = safe_malloc_add_4op_(strlen(tempfile_path_prefix), /*+*/strlen(p), /*+*/strlen(tempfile_suffix), /*+*/2))) {
+		dest_len = strlen(tempfile_path_prefix) + strlen(p) + strlen(tempfile_suffix) + 2;
+
+		if(0 == (*tempfilename = safe_malloc_(dest_len))) {
 			*status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
 			return false;
 		}
-		strcpy(*tempfilename, tempfile_path_prefix);
-		strcat(*tempfilename, "/");
-		strcat(*tempfilename, p);
-		strcat(*tempfilename, tempfile_suffix);
+		safe_strncpy(*tempfilename, tempfile_path_prefix, dest_len);
+		safe_strncat(*tempfilename, "/", dest_len);
+		safe_strncat(*tempfilename, p, dest_len);
+		safe_strncat(*tempfilename, tempfile_suffix, dest_len);
 	}
 
 	if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) {
diff --git a/src/metaflac/utils.c b/src/metaflac/utils.c
index 107be9d..13e7cec 100644
--- a/src/metaflac/utils.c
+++ b/src/metaflac/utils.c
@@ -20,15 +20,16 @@
 #  include <config.h>
 #endif
 
-#include "utils.h"
-#include "FLAC/assert.h"
-#include "share/alloc.h"
-#include "share/utf8.h"
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include "utils.h"
+#include "FLAC/assert.h"
+#include "share/alloc.h"
+#include "share/safe_str.h"
+#include "share/utf8.h"
 
 void die(const char *message)
 {
@@ -72,7 +73,7 @@
 	*dest = safe_realloc_add_3op_(*dest, ndest, /*+*/nsource, /*+*/1);
 	if(0 == *dest)
 		die("out of memory growing string");
-	strcpy((*dest)+ndest, source);
+	safe_strncpy((*dest)+ndest, source, ndest + nsource + 1);
 }
 
 void hexdump(const char *filename, const FLAC__byte *buf, unsigned bytes, const char *indent)
diff --git a/src/monkeys_audio_utilities/flac_mac/main.c b/src/monkeys_audio_utilities/flac_mac/main.c
index c93a9c9..e8582a4 100644
--- a/src/monkeys_audio_utilities/flac_mac/main.c
+++ b/src/monkeys_audio_utilities/flac_mac/main.c
@@ -33,6 +33,8 @@
 #include<process.h>
 #include<winbase.h>
 
+#include "share/safe_str.h"
+
 static int execit(char *prog, char *args);
 static int forkit(char *prog, char *args);
 
@@ -44,11 +46,11 @@
 
 	/* get the directory where MAC external codecs reside */
 	if(0 != (p = strrchr(argv[0],'\\'))) {
-		strcpy(macdir, argv[0]);
+		safe_strncpy(macdir, argv[0], sizeof(macdir));
 		*(strrchr(macdir,'\\')+1) = '\0';
 	}
 	else {
-		strcpy(macdir, "");
+		safe_strncpy(macdir, "", sizeof(macdir));
 	}
 
 	/* determine which codec we were called as and parse the options */
@@ -104,8 +106,8 @@
 	flac_snprintf(options, sizeof (options), "-%d", flac_level);
 	for(i = opt_arg; i < argc; i++)
 		if(argv[i][0] == '-') {
-			strcat(options, " ");
-			strcat(options, argv[i]);
+			safe_strncat(options, " ");
+			safe_strncat(options, argv[i]);
 		}
 	flac_snprintf(cmdline, sizeof (cmdline), "\"%s\" %s -o \"%s\" \"%s\"", prog, options, argv[to_arg], argv[from_arg]);
 
@@ -117,27 +119,46 @@
 	 * it's final resting place.
 	 */
 	if(0 == flac_return_val) {
+		char *cptr;
 		/* get the destination directory, if any */
 		if(0 != (p = strchr(argv[to_arg],'\\'))) {
-			strcpy(from, argv[to_arg]);
+			safe_strncpy(from, argv[to_arg], sizeof(from));
 			*(strrchr(from,'\\')+1) = '\0';
 		}
 		else {
-			strcpy(from, "");
+			safe_strncpy(from, "", sizeof(from));
 		}
 
 		/* for the full 'from' and 'to' paths for the renamer process */
 		p = strrchr(argv[from_arg],'\\');
-		strcat(from, p? p+1 : argv[from_arg]);
-		strcpy(to, from);
-		if(0 == strchr(from,'.'))
+		safe_strncat(from, p? p+1 : argv[from_arg]);
+		safe_strncpy(to, from, sizeof(to));
+
+		cptr = strrchr(from,'.');
+		if(cptr == NULL)
 			return -3;
+		cptr [0] = 0;
+
 		switch(codec) {
-			case SHORTEN: strcpy(strrchr(from,'.'), ".shn"); break;
-			case WAVPACK: strcpy(strrchr(from,'.'), ".wv"); break;
-			case RKAU: strcpy(strrchr(from,'.'), ".rka"); break;
+			case SHORTEN:
+				safe_strncat(from, ".shn", sizeof (from));
+				break;
+			case WAVPACK:
+				safe_strncat(from, ".wv", sizeof (from));
+				break;
+			case RKAU:
+				safe_strncpy(from, ".rka", sizeof (from));
+				break;
+			default:
+				return -4;
 		}
-		strcpy(strrchr(to,'.'), ".flac");
+
+		cptr = strrchr(to,'.');
+		if(cptr == NULL)
+			return -3;
+		cptr [0] = 0;
+
+		safe_strncat(to, ".flac", sizeof(to));
 
 		flac_snprintf(prog, sizeof (prog), "%sflac_ren.exe", macdir);
 		flac_snprintf(cmdline, sizeof (cmdline), "\"%s\" \"%s\" \"%s\"", prog, from, to);
diff --git a/src/share/grabbag/cuesheet.c b/src/share/grabbag/cuesheet.c
index 15ca5f3..76d49c4 100644
--- a/src/share/grabbag/cuesheet.c
+++ b/src/share/grabbag/cuesheet.c
@@ -20,12 +20,13 @@
 #  include <config.h>
 #endif
 
-#include "share/grabbag.h"
-#include "share/compat.h"
-#include "FLAC/assert.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include "FLAC/assert.h"
+#include "share/compat.h"
+#include "share/grabbag.h"
+#include "share/safe_str.h"
 
 unsigned grabbag__cuesheet_msf_to_frame(unsigned minutes, unsigned seconds, unsigned frames)
 {
@@ -292,7 +293,7 @@
 					*error_message = "CD-DA CATALOG number must be 13 decimal digits";
 					return false;
 				}
-				strcpy(cs->media_catalog_number, field);
+				safe_strncpy(cs->media_catalog_number, field, sizeof(cs->media_catalog_number));
 				disc_has_catalog = true;
 			}
 			else if(0 == FLAC__STRCASECMP(field, "FLAGS")) {
@@ -421,7 +422,7 @@
 					*error_message = "invalid ISRC number";
 					return false;
 				}
-				strcpy(cs->tracks[cs->num_tracks-1].isrc, field);
+				safe_strncpy(cs->tracks[cs->num_tracks-1].isrc, field, sizeof(cs->tracks[cs->num_tracks-1].isrc));
 				track_has_isrc = true;
 			}
 			else if(0 == FLAC__STRCASECMP(field, "TRACK")) {
diff --git a/src/share/grabbag/replaygain.c b/src/share/grabbag/replaygain.c
index 8832888..34cac63 100644
--- a/src/share/grabbag/replaygain.c
+++ b/src/share/grabbag/replaygain.c
@@ -20,11 +20,6 @@
 #  include <config.h>
 #endif
 
-#include "share/grabbag.h"
-#include "share/replaygain_analysis.h"
-#include "FLAC/assert.h"
-#include "FLAC/metadata.h"
-#include "FLAC/stream_decoder.h"
 #include <locale.h>
 #include <math.h>
 #include <stdio.h>
@@ -35,6 +30,13 @@
 #endif
 #include <sys/stat.h> /* for stat(), maybe chmod() */
 
+#include "FLAC/assert.h"
+#include "FLAC/metadata.h"
+#include "FLAC/stream_decoder.h"
+#include "share/grabbag.h"
+#include "share/replaygain_analysis.h"
+#include "share/safe_str.h"
+
 #ifdef local_min
 #undef local_min
 #endif
@@ -591,8 +593,7 @@
 	if(0 == q)
 		return false;
 	q++;
-	memset(s, 0, sizeof(s)-1);
-	strncpy(s, q, local_min(sizeof(s)-1, (size_t) (entry->length - (q-p))));
+	safe_strncpy(s, q, local_min(sizeof(s), (size_t) (entry->length - (q-p))));
 
 	v = strtod(s, &end);
 	if(end == s)
diff --git a/src/share/utf8/charset_test.c b/src/share/utf8/charset_test.c
index 1840076..82b6b3f 100644
--- a/src/share/utf8/charset_test.c
+++ b/src/share/utf8/charset_test.c
@@ -119,7 +119,7 @@
   assert(charset_mbtowc(charset, &wc, "\377\277\277\277\277\277", 9) == -1);
 
   /* Encoder */
-  strcpy(s, ".......");
+  safe_strncpy(s, ".......", sizeof(s));
   assert(charset_wctomb(charset, s, 1 << 31) == -1 &&
 	 !strcmp(s, "......."));
   assert(charset_wctomb(charset, s, 127) == 1 &&
@@ -161,7 +161,7 @@
   assert(charset_mbtowc(charset, &wc, "\200", 2) == -1);
 
   /* Encoder */
-  strcpy(s, "..");
+  safe_strncpy(s, "..", sizeof(s));
   assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, ".."));
   assert(charset_wctomb(charset, s, 255) == -1);
   assert(charset_wctomb(charset, s, 128) == -1);
@@ -182,7 +182,7 @@
   assert(charset_mbtowc(charset, &wc, "\302\200", 9) == 1 && wc == 0xc2);
 
   /* Encoder */
-  strcpy(s, "..");
+  safe_strncpy(s, "..", sizeof(s));
   assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, ".."));
   assert(charset_wctomb(charset, s, 255) == 1 && !strcmp(s, "\377."));
   assert(charset_wctomb(charset, s, 128) == 1 && !strcmp(s, "\200."));
@@ -203,7 +203,7 @@
   assert(charset_mbtowc(charset, &wc, "\377", 2) == 1 && wc == 0x2d9);
 
   /* Encoder */
-  strcpy(s, "..");
+  safe_strncpy(s, "..", sizeof(s));
   assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, ".."));
   assert(charset_wctomb(charset, s, 255) == -1 && !strcmp(s, ".."));
   assert(charset_wctomb(charset, s, 258) == 1 && !strcmp(s, "\303."));
@@ -230,7 +230,7 @@
   assert(charset_convert("UTF-8", "iso-8859-1",
 			 "\302\200\304\200x", 5, &q, &n) == 1 &&
 	 n == 3 && !strcmp(q, "\200?x"));
-  assert(charset_convert("iso-8859-1", "UTF-8", 
+  assert(charset_convert("iso-8859-1", "UTF-8",
 			 "\000\200\377", 3, &q, &n) == 0 &&
 	 n == 5 && !memcmp(q, "\000\302\200\303\277", 5));
   assert(charset_convert("iso-8859-1", "iso-8859-1",
diff --git a/src/share/utf8/iconvert.c b/src/share/utf8/iconvert.c
index b5ed2c3..d52deab 100644
--- a/src/share/utf8/iconvert.c
+++ b/src/share/utf8/iconvert.c
@@ -30,6 +30,7 @@
 
 #include "iconvert.h"
 #include "share/alloc.h"
+#include "share/safe_str.h"
 
 /*
  * Convert data from one encoding to another. Return:
@@ -76,18 +77,18 @@
       tocode[4] != '8' ||
       tocode[5] != '\0') {
     char *tocode1;
-
+	size_t dest_len = strlen(tocode) + 11;
     /*
      * Try using this non-standard feature of glibc and libiconv.
      * This is deliberately not a config option as people often
      * change their iconv library without rebuilding applications.
      */
-    tocode1 = safe_malloc_add_2op_(strlen(tocode), /*+*/11);
+    tocode1 = safe_malloc_(dest_len);
     if (!tocode1)
       goto fail;
 
-    strcpy(tocode1, tocode);
-    strcat(tocode1, "//TRANSLIT");
+    safe_strncpy(tocode1, tocode, dest_len);
+    safe_strncat(tocode1, "//TRANSLIT", dest_len);
     cd2 = iconv_open(tocode1, "UTF-8");
     free(tocode1);
 
diff --git a/src/share/utf8/utf8.c b/src/share/utf8/utf8.c
index 48fe355..63827c7 100644
--- a/src/share/utf8/utf8.c
+++ b/src/share/utf8/utf8.c
@@ -31,6 +31,7 @@
 #include <string.h>
 
 #include "share/alloc.h"
+#include "share/safe_str.h"
 #include "utf8.h"
 #include "charset.h"
 
@@ -298,7 +299,7 @@
   s = safe_malloc_add_2op_(fromlen, /*+*/1);
   if (!s)
     return -1;
-  strcpy(s, from);
+  safe_strncpy(s, from, fromlen + 1);
   *to = s;
   for (; *s; s++)
     if (*s & ~0x7f)
diff --git a/src/test_libFLAC/metadata_manip.c b/src/test_libFLAC/metadata_manip.c
index ea51d17..baedd10 100644
--- a/src/test_libFLAC/metadata_manip.c
+++ b/src/test_libFLAC/metadata_manip.c
@@ -38,6 +38,7 @@
 #include "share/grabbag.h"
 #include "share/compat.h"
 #include "share/macros.h"
+#include "share/safe_str.h"
 #include "test_libs_common/file_utils_flac.h"
 #include "test_libs_common/metadata_utils.h"
 #include "metadata.h"
@@ -186,11 +187,11 @@
 static FLAC__bool open_tempfile_(const char *filename, FILE **tempfile, char **tempfilename)
 {
 	static const char *tempfile_suffix = ".metadata_edit";
-
-	if(0 == (*tempfilename = malloc(strlen(filename) + strlen(tempfile_suffix) + 1)))
+	size_t dest_len = strlen(filename) + strlen(tempfile_suffix) + 1;
+	if(0 == (*tempfilename = malloc(dest_len)))
 		return false;
-	strcpy(*tempfilename, filename);
-	strcat(*tempfilename, tempfile_suffix);
+	safe_strncpy(*tempfilename, filename, dest_len);
+	safe_strncat(*tempfilename, tempfile_suffix, dest_len);
 
 	if(0 == (*tempfile = fopen(*tempfilename, "wb")))
 		return false;
@@ -545,7 +546,7 @@
 		if (0 == (cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)))
 			return die_("priming our metadata");
 		cuesheet->is_last = false;
-		strcpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN");
+		safe_strncpy(cuesheet->data.cue_sheet.media_catalog_number, "bogo-MCN", sizeof(cuesheet->data.cue_sheet.media_catalog_number));
 		cuesheet->data.cue_sheet.lead_in = 123;
 		cuesheet->data.cue_sheet.is_cd = false;
 		if (!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, 0))