# Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/components/logger' module Contrast module Extension # Our top level Assess namespace in the Core Extension section of our # code. These patches are those that are invoked directly from a patched # Class. # module Assess # This is the main instrument helper giving the method of requiring C patches # module InstrumentHelper class << self include Contrast::Components::Logger::InstanceMethods # Unites the different require methods into one, using only # the provided path for the C patches # parameters # @param path[String] Path to the required patch # def instrument path var_name, extracted_name = gen_name(path) return if instance_variable_get(var_name) == true instance_variable_set(var_name, assign_value(path)) rescue StandardError, LoadError => e logger.error("Error loading #{ extracted_name&.nil? ? '' : extracted_name } patch", e) false end # Some of the requires have some extra conditions for them to require # the C patches, so this method is helping us move the logic by making some # conditions def assign_value path case path when /fiber/, /interpolation/ require(path) if Funchook.available? else require(path) end true end # Generate the needed instance variable name and return the extracted name def gen_name path extracted_name = path.split(%r{[\s_/]})&.uniq&.delete_if do |s| s.empty? || s == 'cs' || s == 'assess' || s == 'track' end extracted_name = (extracted_name&.length || 0) > 1 ? extracted_name&.join('_') : extracted_name&.pop ["@_instrument_#{ extracted_name }_track", extracted_name] end end end end end end