pw_string: Fix undefined behavior

- Passing nullptr to memcpy or memset is undefined behavior, even if the
  count is zero. Switch to std::fill_n and std::copy_n instead.
- Add a test to cover appending a character to an empty buffer.

Fixed: 539
Change-Id: If942335bfb59bac8fd72d105820886a2a88bd914
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/68584
Reviewed-by: Ted Pudlik <tpudlik@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
diff --git a/pw_string/string_builder.cc b/pw_string/string_builder.cc
index 7eff7d2..3c85eac 100644
--- a/pw_string/string_builder.cc
+++ b/pw_string/string_builder.cc
@@ -29,14 +29,14 @@
 }
 
 StringBuilder& StringBuilder::append(size_t count, char ch) {
-  char* const append_destination = &buffer_[size_];
-  std::memset(append_destination, ch, ResizeAndTerminate(count));
+  char* const append_destination = buffer_.begin() + size_;
+  std::fill_n(append_destination, ResizeAndTerminate(count), ch);
   return *this;
 }
 
 StringBuilder& StringBuilder::append(const char* str, size_t count) {
-  char* const append_destination = &buffer_[size_];
-  std::memcpy(append_destination, str, ResizeAndTerminate(count));
+  char* const append_destination = buffer_.begin() + size_;
+  std::copy_n(str, ResizeAndTerminate(count), append_destination);
   return *this;
 }