diff --git a/Library/Homebrew/dev-cmd/linkage.rb b/Library/Homebrew/dev-cmd/linkage.rb
index c5d43a48dc403f7127d61f277659f58c76eb4531..87a0d9143e378bfd3b4feb63d596656e61590836 100644
--- a/Library/Homebrew/dev-cmd/linkage.rb
+++ b/Library/Homebrew/dev-cmd/linkage.rb
@@ -23,8 +23,7 @@ module Homebrew
       ARGV.kegs.each do |keg|
         ohai "Checking #{keg.name} linkage" if ARGV.kegs.size > 1
 
-        result = LinkageChecker.new(keg, database_cache)
-        result.flush_cache_and_check_dylibs if ARGV.include?("--rebuild")
+        result = LinkageChecker.new(keg, database_cache, ARGV.include?("--rebuild"))
 
         if ARGV.include?("--test")
           result.display_test_output
diff --git a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
index 0386beb9a4ef4fd8947b63be7e33c15eb8a486dc..2b62e6bca73fe560ba12b3452475774f70fe1c5d 100644
--- a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
+++ b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
@@ -65,10 +65,7 @@ module FormulaCellarChecks
     return unless formula.prefix.directory?
     keg = Keg.new(formula.prefix)
 
-    DatabaseCache.new(:linkage) do |database_cache|
-      checker = LinkageChecker.new(keg, database_cache, formula)
-      checker.flush_cache_and_check_dylibs
-    end
+    DatabaseCache.new(:linkage) { |database_cache| LinkageChecker.new(keg, database_cache, true, formula) }
 
     return unless checker.broken_dylibs?
     output = <<~EOS
diff --git a/Library/Homebrew/os/mac/cache_store.rb b/Library/Homebrew/os/mac/cache_store.rb
index fa919d4b4c3688dc5404b871b257c6f1b649bee8..70868dce0cbc3ebbbc850ae6346788cf9d64a9fb 100644
--- a/Library/Homebrew/os/mac/cache_store.rb
+++ b/Library/Homebrew/os/mac/cache_store.rb
@@ -6,13 +6,13 @@ require "json"
 # residing in the `HOMEBREW_CACHE`
 #
 class DatabaseCache
-  # Users have read and write, but not execute permissions
-  DATABASE_MODE = 0666
+  # The mode of any created files will be 0664 (that is, readable and writable
+  # by the owner and the group, and readable by everyone else)
+  DATABASE_MODE = 0664
 
   # Opens and yields a database in read/write mode
-  #
-  # DBM::WRCREAT: Creates the database if it does not already exist
   def initialize(name)
+    # DBM::WRCREAT: Creates the database if it does not already exist
     @db = DBM.open("#{HOMEBREW_CACHE}/#{name}.db", DATABASE_MODE, DBM::WRCREAT)
     yield(@db)
     @db.close
@@ -47,16 +47,24 @@ class CacheStore
 
   protected
 
+  # @return [DBM]
   attr_reader :database_cache
 
-  # Parses `DBM` stored `String` into ruby `Hash`
-  #
   # DBM stores ruby objects as a ruby `String`. Hence, when fetching the data,
   # to convert the ruby string back into a ruby `Hash`, the string is converted
-  # into a JSON compatible string, where it may be parsed by the JSON.parse
-  # function
-  def string_to_hash(string)
-    JSON.parse(string.gsub("=>", ":"))
+  # into a JSON compatible string in `ruby_hash_to_json_string`, where it may
+  # later be parsed by `JSON.parse` in the `json_string_to_ruby_hash` method
+  #
+  # @param  [Hash]
+  # @return [String]
+  def ruby_hash_to_json_string(hash)
+    hash.to_json
+  end
+
+  # @param  [String]
+  # @return [Hash]
+  def json_string_to_ruby_hash(string)
+    JSON.parse(string)
   end
 end
 
@@ -73,7 +81,7 @@ class LinkageStore < CacheStore
   end
 
   def update!(
-    path_values: {
+    array_values: {
       system_dylibs: %w[],
       variable_dylibs: %w[],
       broken_dylibs: %w[],
@@ -86,17 +94,17 @@ class LinkageStore < CacheStore
       reverse_links: {},
     }
   )
-    database_cache[keg_name] = {
-      "path_values" => format_path_values(path_values),
-      "hash_values" => format_hash_values(hash_values),
-    }
+    database_cache[keg_name] = ruby_hash_to_json_string(
+      array_values: format_array_values(array_values),
+      hash_values: format_hash_values(hash_values),
+    )
   end
 
   def fetch_type(type)
     if HASH_LINKAGE_TYPES.include?(type)
       fetch_hash_values(type: type)
     else
-      fetch_path_values(type: type)
+      fetch_array_values(type: type)
     end
   end
 
@@ -108,28 +116,33 @@ class LinkageStore < CacheStore
 
   attr_reader :keg_name
 
-  def fetch_path_values(type:)
-    return [] if !database_cache.key?(keg_name) || database_cache[keg_name].nil?
-    string_to_hash(database_cache[keg_name])["path_values"][type.to_s]
+  def fetch_array_values(type:)
+    return [] unless database_cache.key?(keg_name)
+    json_string_to_ruby_hash(database_cache[keg_name])["array_values"][type.to_s]
   end
 
   def fetch_hash_values(type:)
-    return {} if !database_cache.key?(keg_name) || database_cache[keg_name].nil?
-    string_to_hash(database_cache[keg_name])["hash_values"][type.to_s]
+    return {} unless database_cache.key?(keg_name)
+    json_string_to_ruby_hash(database_cache[keg_name])["hash_values"][type.to_s]
   end
 
-  # Formats the linkage data for `path_values` into a kind which can be parsed
-  # by the `string_to_hash` method. Converts ruby `Set`s to `Array`s
-  def format_path_values(hash)
-    hash.each_with_object({}) { |(k, v), h| h[k.to_s] = v.to_a }
+  # Formats the linkage data for `array_values` into a kind which can be parsed
+  # by the `json_string_to_ruby_hash` method. Internally converts ruby `Set`s to
+  # `Array`s
+  #
+  # @return [String]
+  def format_array_values(hash)
+    hash.each_with_object({}) { |(k, v), h| h[k] = v.to_a }
   end
 
   # Formats the linkage data for `hash_values` into a kind which can be parsed
-  # by the `string_to_hash` method. Converts ruby `Set`s to `Array`s, and
+  # by the `json_string_to_ruby_hash` method. Converts ruby `Set`s to `Array`s, and
   # converts ruby `Pathname`s to `String`s
+  #
+  # @return [String]
   def format_hash_values(hash)
     hash.each_with_object({}) do |(outer_key, outer_values), outer_hash|
-      outer_hash[outer_key.to_s] = outer_values.each_with_object({}) do |(k, v), h|
+      outer_hash[outer_key] = outer_values.each_with_object({}) do |(k, v), h|
         h[k] = v.to_a.map(&:to_s)
       end
     end
diff --git a/Library/Homebrew/os/mac/linkage_checker.rb b/Library/Homebrew/os/mac/linkage_checker.rb
index 650cea0e9f40ff0408ca3c35ee578e19d8b0555e..ed5eb8acd027f5874859a27f8e5d2610cb583d6e 100644
--- a/Library/Homebrew/os/mac/linkage_checker.rb
+++ b/Library/Homebrew/os/mac/linkage_checker.rb
@@ -6,10 +6,11 @@ require "os/mac/cache_store"
 class LinkageChecker
   attr_reader :keg, :formula, :store
 
-  def initialize(keg, db, formula = nil)
+  def initialize(keg, db, rebuild_cache = false, formula = nil)
     @keg = keg
     @formula = formula || resolve_formula(keg)
     @store = LinkageStore.new(keg.name, db)
+    flush_cache_and_check_dylibs if rebuild_cache
   end
 
   # 'Hash-type' cache values
@@ -222,7 +223,7 @@ class LinkageChecker
   # Updates data store with package path values
   def store_dylibs!
     store.update!(
-      path_values: {
+      array_values: {
         system_dylibs: @system_dylibs,
         variable_dylibs: @variable_dylibs,
         broken_dylibs: @broken_dylibs,