Merge "Refactor existing tests to use gtest"
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index 036b6f5..2215194 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -21,7 +21,7 @@
 LOCAL_MODULE := libapplypatch
 LOCAL_MODULE_TAGS := eng
 LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libbase libmtdutils libmincrypt libbz libz
+LOCAL_STATIC_LIBRARIES += libbase libmtdutils libcrypto_static libbz libz
 
 include $(BUILD_STATIC_LIBRARY)
 
@@ -32,7 +32,7 @@
 LOCAL_MODULE := libimgpatch
 LOCAL_C_INCLUDES += bootable/recovery
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES += libmincrypt libbz libz
+LOCAL_STATIC_LIBRARIES += libcrypto_static libbz libz
 
 include $(BUILD_STATIC_LIBRARY)
 
@@ -44,7 +44,7 @@
 LOCAL_MODULE := libimgpatch
 LOCAL_C_INCLUDES += bootable/recovery
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES += libmincrypt libbz libz
+LOCAL_STATIC_LIBRARIES += libcrypto_static libbz libz
 
 include $(BUILD_HOST_STATIC_LIBRARY)
 endif  # HOST_OS == linux
@@ -55,7 +55,7 @@
 LOCAL_SRC_FILES := main.cpp
 LOCAL_MODULE := applypatch
 LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libapplypatch libbase libmtdutils libmincrypt libbz
+LOCAL_STATIC_LIBRARIES += libapplypatch libbase libmtdutils libcrypto_static libbz
 LOCAL_SHARED_LIBRARIES += libz libcutils libc
 
 include $(BUILD_EXECUTABLE)
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index f9425af..75ffe0f 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -27,7 +27,7 @@
 
 #include <android-base/strings.h>
 
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
 #include "applypatch.h"
 #include "mtdutils/mtdutils.h"
 #include "edify/expr.h"
@@ -41,7 +41,7 @@
                           const Value* copy_patch_value,
                           const char* source_filename,
                           const char* target_filename,
-                          const uint8_t target_sha1[SHA_DIGEST_SIZE],
+                          const uint8_t target_sha1[SHA_DIGEST_LENGTH],
                           size_t target_size,
                           const Value* bonus_data);
 
@@ -86,7 +86,7 @@
     }
     fclose(f);
 
-    SHA_hash(file->data, file->size, file->sha1);
+    SHA1(file->data, file->size, file->sha1);
     return 0;
 }
 
@@ -181,8 +181,8 @@
     }
 
     SHA_CTX sha_ctx;
-    SHA_init(&sha_ctx);
-    uint8_t parsed_sha[SHA_DIGEST_SIZE];
+    SHA1_Init(&sha_ctx);
+    uint8_t parsed_sha[SHA_DIGEST_LENGTH];
 
     // Allocate enough memory to hold the largest size.
     file->data = reinterpret_cast<unsigned char*>(malloc(size[index[pairs-1]]));
@@ -212,7 +212,7 @@
                 file->data = NULL;
                 return -1;
             }
-            SHA_update(&sha_ctx, p, read);
+            SHA1_Update(&sha_ctx, p, read);
             file->size += read;
         }
 
@@ -220,7 +220,8 @@
         // check it against this pair's expected hash.
         SHA_CTX temp_ctx;
         memcpy(&temp_ctx, &sha_ctx, sizeof(SHA_CTX));
-        const uint8_t* sha_so_far = SHA_final(&temp_ctx);
+        uint8_t sha_so_far[SHA_DIGEST_LENGTH];
+        SHA1_Final(sha_so_far, &temp_ctx);
 
         if (ParseSha1(sha1sum[index[i]].c_str(), parsed_sha) != 0) {
             printf("failed to parse sha1 %s in %s\n", sha1sum[index[i]].c_str(), filename);
@@ -229,7 +230,7 @@
             return -1;
         }
 
-        if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_SIZE) == 0) {
+        if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_LENGTH) == 0) {
             // we have a match.  stop reading the partition; we'll return
             // the data we've read so far.
             printf("partition read matched size %zu sha %s\n",
@@ -260,10 +261,7 @@
         return -1;
     }
 
-    const uint8_t* sha_final = SHA_final(&sha_ctx);
-    for (size_t i = 0; i < SHA_DIGEST_SIZE; ++i) {
-        file->sha1[i] = sha_final[i];
-    }
+    SHA1_Final(file->sha1, &sha_ctx);
 
     // Fake some stat() info.
     file->st.st_mode = 0644;
@@ -494,7 +492,7 @@
 int ParseSha1(const char* str, uint8_t* digest) {
     const char* ps = str;
     uint8_t* pd = digest;
-    for (int i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
+    for (int i = 0; i < SHA_DIGEST_LENGTH * 2; ++i, ++ps) {
         int digit;
         if (*ps >= '0' && *ps <= '9') {
             digit = *ps - '0';
@@ -521,10 +519,10 @@
 // found.
 int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
                       int num_patches) {
-    uint8_t patch_sha1[SHA_DIGEST_SIZE];
+    uint8_t patch_sha1[SHA_DIGEST_LENGTH];
     for (int i = 0; i < num_patches; ++i) {
         if (ParseSha1(patch_sha1_str[i], patch_sha1) == 0 &&
-            memcmp(patch_sha1, sha1, SHA_DIGEST_SIZE) == 0) {
+            memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) {
             return i;
         }
     }
@@ -670,7 +668,7 @@
         target_filename = source_filename;
     }
 
-    uint8_t target_sha1[SHA_DIGEST_SIZE];
+    uint8_t target_sha1[SHA_DIGEST_LENGTH];
     if (ParseSha1(target_sha1_str, target_sha1) != 0) {
         printf("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
         return 1;
@@ -685,7 +683,7 @@
 
     // We try to load the target file into the source_file object.
     if (LoadFileContents(target_filename, &source_file) == 0) {
-        if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
+        if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) == 0) {
             // The early-exit case:  the patch was already applied, this file
             // has the desired hash, nothing for us to do.
             printf("already %s\n", short_sha1(target_sha1).c_str());
@@ -756,7 +754,7 @@
                      const char* target_sha1_str, size_t target_size) {
     printf("flash %s: ", target_filename);
 
-    uint8_t target_sha1[SHA_DIGEST_SIZE];
+    uint8_t target_sha1[SHA_DIGEST_LENGTH];
     if (ParseSha1(target_sha1_str, target_sha1) != 0) {
         printf("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
         return 1;
@@ -777,7 +775,7 @@
     pieces.push_back(target_sha1_str);
     std::string fullname = android::base::Join(pieces, ':');
     if (LoadPartitionContents(fullname.c_str(), &source_file) == 0 &&
-        memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
+        memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) == 0) {
         // The early-exit case: the image was already applied, this partition
         // has the desired hash, nothing for us to do.
         printf("already %s\n", short_sha1(target_sha1).c_str());
@@ -786,7 +784,7 @@
     }
 
     if (LoadFileContents(source_filename, &source_file) == 0) {
-        if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
+        if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) != 0) {
             // The source doesn't have desired checksum.
             printf("source \"%s\" doesn't have expected sha1 sum\n", source_filename);
             printf("expected: %s, found: %s\n", short_sha1(target_sha1).c_str(),
@@ -812,7 +810,7 @@
                           const Value* copy_patch_value,
                           const char* source_filename,
                           const char* target_filename,
-                          const uint8_t target_sha1[SHA_DIGEST_SIZE],
+                          const uint8_t target_sha1[SHA_DIGEST_LENGTH],
                           size_t target_size,
                           const Value* bonus_data) {
     int retry = 1;
@@ -957,7 +955,7 @@
         char* header = patch->data;
         ssize_t header_bytes_read = patch->size;
 
-        SHA_init(&ctx);
+        SHA1_Init(&ctx);
 
         int result;
 
@@ -1001,8 +999,9 @@
         }
     } while (retry-- > 0);
 
-    const uint8_t* current_target_sha1 = SHA_final(&ctx);
-    if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
+    uint8_t current_target_sha1[SHA_DIGEST_LENGTH];
+    SHA1_Final(current_target_sha1, &ctx);
+    if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_LENGTH) != 0) {
         printf("patch did not produce expected sha1\n");
         return 1;
     } else {
diff --git a/applypatch/applypatch.h b/applypatch/applypatch.h
index 415bc1b..e0df104 100644
--- a/applypatch/applypatch.h
+++ b/applypatch/applypatch.h
@@ -18,16 +18,16 @@
 #define _APPLYPATCH_H
 
 #include <sys/stat.h>
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
 #include "edify/expr.h"
 
 typedef struct _Patch {
-  uint8_t sha1[SHA_DIGEST_SIZE];
+  uint8_t sha1[SHA_DIGEST_LENGTH];
   const char* patch_filename;
 } Patch;
 
 typedef struct _FileContents {
-  uint8_t sha1[SHA_DIGEST_SIZE];
+  uint8_t sha1[SHA_DIGEST_LENGTH];
   unsigned char* data;
   ssize_t size;
   struct stat st;
diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp
index 75975ad..2517117 100644
--- a/applypatch/bspatch.cpp
+++ b/applypatch/bspatch.cpp
@@ -30,7 +30,7 @@
 
 #include <bzlib.h>
 
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
 #include "applypatch.h"
 
 void ShowBSDiffLicense() {
@@ -114,7 +114,7 @@
         printf("short write of output: %d (%s)\n", errno, strerror(errno));
         return 1;
     }
-    if (ctx) SHA_update(ctx, new_data, new_size);
+    if (ctx) SHA1_Update(ctx, new_data, new_size);
     free(new_data);
 
     return 0;
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index 3e72b2c..c9944df 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -26,7 +26,7 @@
 #include <string.h>
 
 #include "zlib.h"
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
 #include "applypatch.h"
 #include "imgdiff.h"
 #include "utils.h"
@@ -109,7 +109,7 @@
                 printf("failed to read chunk %d raw data\n", i);
                 return -1;
             }
-            if (ctx) SHA_update(ctx, patch->data + pos, data_len);
+            if (ctx) SHA1_Update(ctx, patch->data + pos, data_len);
             if (sink((unsigned char*)patch->data + pos,
                      data_len, token) != data_len) {
                 printf("failed to write chunk %d raw data\n", i);
@@ -236,7 +236,7 @@
                            (long)have);
                     return -1;
                 }
-                if (ctx) SHA_update(ctx, temp_data, have);
+                if (ctx) SHA1_Update(ctx, temp_data, have);
             } while (ret != Z_STREAM_END);
             deflateEnd(&strm);
 
diff --git a/applypatch/main.cpp b/applypatch/main.cpp
index 966d8b9..445a7fe 100644
--- a/applypatch/main.cpp
+++ b/applypatch/main.cpp
@@ -21,7 +21,7 @@
 
 #include "applypatch.h"
 #include "edify/expr.h"
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
 
 static int CheckMode(int argc, char** argv) {
     if (argc < 3) {
@@ -54,7 +54,7 @@
     *patches = reinterpret_cast<Value**>(malloc(*num_patches * sizeof(Value*)));
     memset(*patches, 0, *num_patches * sizeof(Value*));
 
-    uint8_t digest[SHA_DIGEST_SIZE];
+    uint8_t digest[SHA_DIGEST_LENGTH];
 
     for (int i = 0; i < *num_patches; ++i) {
         char* colon = strchr(argv[i], ':');
diff --git a/print_sha1.h b/print_sha1.h
index 9e37c5f..fa3d7e0 100644
--- a/print_sha1.h
+++ b/print_sha1.h
@@ -20,9 +20,9 @@
 #include <stdint.h>
 #include <string>
 
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
 
-static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_SIZE], size_t len) {
+static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH], size_t len) {
     const char* hex = "0123456789abcdef";
     std::string result = "";
     for (size_t i = 0; i < len; ++i) {
@@ -32,11 +32,11 @@
     return result;
 }
 
-static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]) {
-    return print_sha1(sha1, SHA_DIGEST_SIZE);
+static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH]) {
+    return print_sha1(sha1, SHA_DIGEST_LENGTH);
 }
 
-static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]) {
+static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH]) {
     return print_sha1(sha1, 4);
 }
 
diff --git a/updater/Android.mk b/updater/Android.mk
index dcf4374..6fdd308 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -46,7 +46,7 @@
 
 LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
 LOCAL_STATIC_LIBRARIES += libapplypatch libbase libedify libmtdutils libminzip libz
-LOCAL_STATIC_LIBRARIES += libmincrypt libbz
+LOCAL_STATIC_LIBRARIES += libbz
 LOCAL_STATIC_LIBRARIES += libcutils liblog libc
 LOCAL_STATIC_LIBRARIES += libselinux
 tune2fs_static_libraries := \
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index c6daf7d..6e05600 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -43,7 +43,7 @@
 #include "applypatch/applypatch.h"
 #include "edify/expr.h"
 #include "install.h"
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
 #include "minzip/Hash.h"
 #include "print_sha1.h"
 #include "unique_fd.h"
@@ -407,10 +407,10 @@
 
 static int VerifyBlocks(const std::string& expected, const std::vector<uint8_t>& buffer,
         const size_t blocks, bool printerror) {
-    uint8_t digest[SHA_DIGEST_SIZE];
+    uint8_t digest[SHA_DIGEST_LENGTH];
     const uint8_t* data = buffer.data();
 
-    SHA_hash(data, blocks * BLOCKSIZE, digest);
+    SHA1(data, blocks * BLOCKSIZE, digest);
 
     std::string hexdigest = print_sha1(digest);
 
@@ -662,10 +662,8 @@
     // Stash directory should be different for each partition to avoid conflicts
     // when updating multiple partitions at the same time, so we use the hash of
     // the block device name as the base directory
-    SHA_CTX ctx;
-    SHA_init(&ctx);
-    SHA_update(&ctx, blockdev, strlen(blockdev));
-    const uint8_t* digest = SHA_final(&ctx);
+    uint8_t digest[SHA_DIGEST_LENGTH];
+    SHA1(reinterpret_cast<const uint8_t*>(blockdev), strlen(blockdev), digest);
     base = print_sha1(digest);
 
     std::string dirname = GetStashFileName(base, "", "");
@@ -1627,7 +1625,7 @@
     parse_range(ranges->data, rs);
 
     SHA_CTX ctx;
-    SHA_init(&ctx);
+    SHA1_Init(&ctx);
 
     std::vector<uint8_t> buffer(BLOCKSIZE);
     for (size_t i = 0; i < rs.count; ++i) {
@@ -1643,10 +1641,11 @@
                 return StringValue(strdup(""));
             }
 
-            SHA_update(&ctx, buffer.data(), BLOCKSIZE);
+            SHA1_Update(&ctx, buffer.data(), BLOCKSIZE);
         }
     }
-    const uint8_t* digest = SHA_final(&ctx);
+    uint8_t digest[SHA_DIGEST_LENGTH];
+    SHA1_Final(digest, &ctx);
 
     return StringValue(strdup(print_sha1(digest).c_str()));
 }
diff --git a/updater/install.cpp b/updater/install.cpp
index b090869..45bbf2b 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -34,6 +34,9 @@
 #include <linux/xattr.h>
 #include <inttypes.h>
 
+#include <memory>
+#include <vector>
+
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 #include <android-base/stringprintf.h>
@@ -44,7 +47,7 @@
 #include "cutils/misc.h"
 #include "cutils/properties.h"
 #include "edify/expr.h"
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
 #include "minzip/DirUtil.h"
 #include "mtdutils/mounts.h"
 #include "mtdutils/mtdutils.h"
@@ -91,10 +94,10 @@
 
 // Take a sha-1 digest and return it as a newly-allocated hex string.
 char* PrintSha1(const uint8_t* digest) {
-    char* buffer = reinterpret_cast<char*>(malloc(SHA_DIGEST_SIZE*2 + 1));
+    char* buffer = reinterpret_cast<char*>(malloc(SHA_DIGEST_LENGTH*2 + 1));
     const char* alphabet = "0123456789abcdef";
     size_t i;
-    for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
+    for (i = 0; i < SHA_DIGEST_LENGTH; ++i) {
         buffer[i*2] = alphabet[(digest[i] >> 4) & 0xf];
         buffer[i*2+1] = alphabet[digest[i] & 0xf];
     }
@@ -439,8 +442,7 @@
     for (int i = 0; i < argc; ++i) {
         paths[i] = Evaluate(state, argv[i]);
         if (paths[i] == NULL) {
-            int j;
-            for (j = 0; j < i; ++i) {
+            for (int j = 0; j < i; ++j) {
                 free(paths[j]);
             }
             free(paths);
@@ -581,13 +583,13 @@
         // as the result.
 
         char* zip_path;
+        if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL;
+
         Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value)));
         v->type = VAL_BLOB;
         v->size = -1;
         v->data = NULL;
 
-        if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL;
-
         ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
         const ZipEntry* entry = mzFindZipEntry(za, zip_path);
         if (entry == NULL) {
@@ -1193,44 +1195,40 @@
     }
 
     int patchcount = (argc-4) / 2;
-    Value** patches = ReadValueVarArgs(state, argc-4, argv+4);
+    std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc-4, argv+4),
+                                                        free);
+    if (!arg_values) {
+        return nullptr;
+    }
+    std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patch_shas;
+    std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patches;
+    // Protect values by unique_ptrs first to get rid of memory leak.
+    for (int i = 0; i < patchcount * 2; i += 2) {
+        patch_shas.emplace_back(arg_values.get()[i], FreeValue);
+        patches.emplace_back(arg_values.get()[i+1], FreeValue);
+    }
 
-    int i;
-    for (i = 0; i < patchcount; ++i) {
-        if (patches[i*2]->type != VAL_STRING) {
+    for (int i = 0; i < patchcount; ++i) {
+        if (patch_shas[i]->type != VAL_STRING) {
             ErrorAbort(state, "%s(): sha-1 #%d is not string", name, i);
-            break;
+            return nullptr;
         }
-        if (patches[i*2+1]->type != VAL_BLOB) {
+        if (patches[i]->type != VAL_BLOB) {
             ErrorAbort(state, "%s(): patch #%d is not blob", name, i);
-            break;
+            return nullptr;
         }
     }
-    if (i != patchcount) {
-        for (i = 0; i < patchcount*2; ++i) {
-            FreeValue(patches[i]);
-        }
-        free(patches);
-        return NULL;
-    }
 
-    char** patch_sha_str = reinterpret_cast<char**>(malloc(patchcount * sizeof(char*)));
-    for (i = 0; i < patchcount; ++i) {
-        patch_sha_str[i] = patches[i*2]->data;
-        patches[i*2]->data = NULL;
-        FreeValue(patches[i*2]);
-        patches[i] = patches[i*2+1];
+    std::vector<char*> patch_sha_str;
+    std::vector<Value*> patch_ptrs;
+    for (int i = 0; i < patchcount; ++i) {
+        patch_sha_str.push_back(patch_shas[i]->data);
+        patch_ptrs.push_back(patches[i].get());
     }
 
     int result = applypatch(source_filename, target_filename,
                             target_sha1, target_size,
-                            patchcount, patch_sha_str, patches, NULL);
-
-    for (i = 0; i < patchcount; ++i) {
-        FreeValue(patches[i]);
-    }
-    free(patch_sha_str);
-    free(patches);
+                            patchcount, patch_sha_str.data(), patch_ptrs.data(), NULL);
 
     return StringValue(strdup(result == 0 ? "t" : ""));
 }
@@ -1349,24 +1347,27 @@
         return ErrorAbort(state, "%s() expects at least 1 arg", name);
     }
 
-    Value** args = ReadValueVarArgs(state, argc, argv);
-    if (args == NULL) {
-        return NULL;
+    std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free);
+    if (arg_values == nullptr) {
+        return nullptr;
+    }
+    std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> args;
+    for (int i = 0; i < argc; ++i) {
+        args.emplace_back(arg_values.get()[i], FreeValue);
     }
 
     if (args[0]->size < 0) {
         return StringValue(strdup(""));
     }
-    uint8_t digest[SHA_DIGEST_SIZE];
-    SHA_hash(args[0]->data, args[0]->size, digest);
-    FreeValue(args[0]);
+    uint8_t digest[SHA_DIGEST_LENGTH];
+    SHA1(reinterpret_cast<uint8_t*>(args[0]->data), args[0]->size, digest);
 
     if (argc == 1) {
         return StringValue(PrintSha1(digest));
     }
 
     int i;
-    uint8_t* arg_digest = reinterpret_cast<uint8_t*>(malloc(SHA_DIGEST_SIZE));
+    uint8_t arg_digest[SHA_DIGEST_LENGTH];
     for (i = 1; i < argc; ++i) {
         if (args[i]->type != VAL_STRING) {
             printf("%s(): arg %d is not a string; skipping",
@@ -1375,22 +1376,16 @@
             // Warn about bad args and skip them.
             printf("%s(): error parsing \"%s\" as sha-1; skipping",
                    name, args[i]->data);
-        } else if (memcmp(digest, arg_digest, SHA_DIGEST_SIZE) == 0) {
+        } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) {
             break;
         }
-        FreeValue(args[i]);
     }
     if (i >= argc) {
         // Didn't match any of the hex strings; return false.
         return StringValue(strdup(""));
     }
-    // Found a match; free all the remaining arguments and return the
-    // matched one.
-    int j;
-    for (j = i+1; j < argc; ++j) {
-        FreeValue(args[j]);
-    }
-    return args[i];
+    // Found a match.
+    return args[i].release();
 }
 
 // Read a local file and return its contents (the Value* returned