[Filesystem] Fix for readString methods 92/185992/8
authorSzymon Jastrzebski <s.jastrzebsk@partner.samsung.com>
Mon, 13 Aug 2018 12:22:57 +0000 (14:22 +0200)
committerSzymon Jastrzebski <s.jastrzebsk@partner.samsung.com>
Tue, 14 Aug 2018 08:26:01 +0000 (10:26 +0200)
+ The readString methods reported string till the first null character.
  This is wrong, because files may contain 0x00 bytes.
+ The returned string contains exactly at most 'count' characters.
  The returned string does not contain additional null characters.

[ACR] http://suprem.sec.samsung.net/jira/browse/TWDAPI-121

[Verification] TCT 100%

Code works well with below snippet:

var fileHandleWrite = tizen.filesystem.openFile("documents/filet", "w");
fileHandleWrite.writeString("Lorem ipsum\x00\x00dolor sit amet...");

var fileHandleRead = tizen.filesystem.openFile("documents/filet", "r");
var fileContents = fileHandleRead.readString();

The 'fileContents is equal to:
"Lorem ipsum"\x00\x00"dolor sit amet..."

Change-Id: Id56c365e701c4ba88bdeeb7a4851669250f332b4
Signed-off-by: Szymon Jastrzebski <s.jastrzebsk@partner.samsung.com>
src/filesystem/filesystem_instance.cc

index 112f7e5..0837d5e 100644 (file)
@@ -383,7 +383,8 @@ static std::size_t file_bytes_to_eof(FILE* file) {
   return total_fize_size - static_cast<size_t>(file_position);
 }
 
-static std::vector<std::uint8_t> read_file(FILE* file, std::size_t length = NPOS);
+static std::vector<std::uint8_t> read_file(FILE* file, std::size_t length = NPOS,
+                                           std::size_t* read_bytes = nullptr);
 
 /**
  * Returns a buffer. If length is NPOS, then it reads whole file, up to the end.
@@ -422,7 +423,8 @@ static std::vector<std::uint8_t> read_file(std::string path, long offset = 0,
  * Returns a buffer. If length is NPOS, then it reads whole file, up to the end.
  * On failure throws std::runtime_error
  */
-static std::vector<std::uint8_t> read_file(FILE* file, std::size_t length /*= NPOS*/) {
+static std::vector<std::uint8_t> read_file(FILE* file, std::size_t length /*= NPOS*/,
+                                           std::size_t* read_bytes /* = nullptr*/) {
   ScopeLogger();
 
   // By default reads whole file. Get the file size.
@@ -451,6 +453,14 @@ static std::vector<std::uint8_t> read_file(FILE* file, std::size_t length /*= NP
       break;
     }
   }
+  // read_file function is used in API since version 1.0.
+  // read_bytes was added in Tizen 5.0, with default value equal to nullptr, the behaviour is not
+  // changed.
+  // It is used to return the actual number of read bytes, because requested length might be bigger
+  // than possible bytes to be read.
+  if (nullptr != read_bytes) {
+    *read_bytes = std::distance(out_buf.data(), data_p);
+  }
   return out_buf;
 }
 
@@ -1981,7 +1991,9 @@ void FilesystemInstance::FileHandleReadString(const picojson::value& args, picoj
 
   auto logic = [handle, count, encoding, whole_file](decltype(out) out) {
     try {
-      std::vector<std::uint8_t> buf = read_file(handle->file_handle, count);
+      size_t read_bytes = 0;
+      std::vector<std::uint8_t> buf = read_file(handle->file_handle, count, &read_bytes);
+      buf.resize(read_bytes);          // this protects from reporting too big arrays to JS
       if (encoding == kISOEncoding) {  // for iso-8859-1 1 byte is equal to 1 character
         out["result"] = picojson::value(picojson::string_type, true);
         latin1::to_utf8(buf, out["result"].get<std::string>());
@@ -2006,9 +2018,8 @@ void FilesystemInstance::FileHandleReadString(const picojson::value& args, picoj
                 IOException("File doesn't contain UTF-8 encoded string with given length"), out);
           }
         }
-        buf.push_back('\0');
         const char* str = (const char*)buf.data();
-        ReportSuccess(picojson::value{str}, out);
+        ReportSuccess(picojson::value{str, buf.size()}, out);
       }
     } catch (std::runtime_error& e) {
       LoggerE("Cannot read, cause: %s", e.what());