def auto_patch(self, addr: int, new_bytes: bytearray):
        """
        Automatically update or create patches to ensure new_bytes are patched at addr.
        """
        pm = self.instance.project.kb.patches
        max_addr = addr + len(new_bytes) - 1

        for p in pm.get_all_patches(addr, len(new_bytes)):
            patch_max_addr = p.addr + len(p) - 1
            if (p.addr <= addr) and (patch_max_addr >= max_addr):
                # Existing patch contains new patch entirely. Update it.
                p.new_bytes = p.new_bytes[: addr - p.addr] + new_bytes + p.new_bytes[max_addr - p.addr + 1 :]
                return
            elif (p.addr >= addr) and (patch_max_addr <= max_addr):
                # Patch will be entirely overwritten, remove it.
                pm.remove_patch(p.addr)
            elif (p.addr >= addr) and (patch_max_addr > max_addr):
                # Lower portion of patch will be overwritten, shrink patch up.
                pm.remove_patch(p.addr)
                new_p_addr = max_addr + 1
                p.new_bytes = p.new_bytes[(new_p_addr - p.addr) :]
                p.addr = new_p_addr
                pm.add_patch_obj(p)
            elif (p.addr < addr) and (patch_max_addr <= max_addr):
                # Upper portion of patch will be overwritten, shrink patch down.
                pm.remove_patch(p.addr)
                p.new_bytes = p.new_bytes[0 : (addr - p.addr)]
                pm.add_patch_obj(p)
            else:
                raise AssertionError

        # Check to see if we should extend an adjacent patch
        if addr > 0:
            p = pm.get_all_patches(addr - 1, 1)
            if len(p) > 0:
                p = p[0]
                p.new_bytes += new_bytes
                return

        pm.add_patch_obj(Patch(addr, new_bytes))

        Automatically update or create patches to ensure new_bytes are patched at addr.
        
angrmanagement/ui/views/hex_view.py