|
74 | 74 | #endif // LOADER_ENABLE_LINUX_SORT |
75 | 75 |
|
76 | 76 | // Generated file containing all the extension data |
| 77 | +// NOLINTNEXTLINE(bugprone-suspicious-include) - intentionally including a .c file to inline generated tables |
77 | 78 | #include "vk_loader_extensions.c" |
78 | 79 |
|
79 | 80 | struct loader_struct loader = {0}; |
@@ -701,21 +702,21 @@ uint32_t loader_parse_version_string(char *vers_str) { |
701 | 702 |
|
702 | 703 | vers_tok = thread_safe_strtok(vers_str, ".\"\n\r", &context); |
703 | 704 | if (NULL != vers_tok) { |
704 | | - major = (uint16_t)atoi(vers_tok); |
| 705 | + major = (uint16_t)strtoul(vers_tok, NULL, 10); |
705 | 706 | vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context); |
706 | 707 | if (NULL != vers_tok) { |
707 | | - minor = (uint16_t)atoi(vers_tok); |
| 708 | + minor = (uint16_t)strtoul(vers_tok, NULL, 10); |
708 | 709 | vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context); |
709 | 710 | if (NULL != vers_tok) { |
710 | | - patch = (uint16_t)atoi(vers_tok); |
| 711 | + patch = (uint16_t)strtoul(vers_tok, NULL, 10); |
711 | 712 | vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context); |
712 | 713 | // check that we are using a 4 part version string |
713 | 714 | if (NULL != vers_tok) { |
714 | 715 | // if we are, move the values over into the correct place |
715 | 716 | variant = major; |
716 | 717 | major = minor; |
717 | 718 | minor = patch; |
718 | | - patch = (uint16_t)atoi(vers_tok); |
| 719 | + patch = (uint16_t)strtoul(vers_tok, NULL, 10); |
719 | 720 | } |
720 | 721 | } |
721 | 722 | } |
@@ -1168,6 +1169,8 @@ VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loade |
1168 | 1169 | ext_list->capacity *= 2; |
1169 | 1170 | } |
1170 | 1171 |
|
| 1172 | + // every caller passes the address of an array element or on-stack struct, never NULL |
| 1173 | + // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker) |
1171 | 1174 | memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties)); |
1172 | 1175 | ext_list->count++; |
1173 | 1176 | } |
@@ -1213,6 +1216,8 @@ VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct l |
1213 | 1216 | ext_list->capacity *= 2; |
1214 | 1217 | } |
1215 | 1218 |
|
| 1219 | + // every caller passes the address of an array element or on-stack struct, never NULL |
| 1220 | + // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker) |
1216 | 1221 | memcpy(&ext_list->list[idx].props, props, sizeof(*props)); |
1217 | 1222 | if (entrys) { |
1218 | 1223 | ext_list->list[idx].entrypoints = *entrys; |
@@ -1592,7 +1597,7 @@ VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance |
1592 | 1597 |
|
1593 | 1598 | // Check if a user wants to disable the instance extension filtering behavior |
1594 | 1599 | env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst); |
1595 | | - if (NULL != env_value && atoi(env_value) != 0) { |
| 1600 | + if (NULL != env_value && strtol(env_value, NULL, 10) != 0) { |
1596 | 1601 | filter_extensions = false; |
1597 | 1602 | } |
1598 | 1603 | loader_free_getenv(env_value, inst); |
@@ -2358,6 +2363,7 @@ void loader_initialize(void) { |
2358 | 2363 |
|
2359 | 2364 | char *loader_disable_dynamic_library_unloading_env_var = loader_getenv("VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING", NULL); |
2360 | 2365 | if (loader_disable_dynamic_library_unloading_env_var && |
| 2366 | + // NOLINTNEXTLINE(bugprone-not-null-terminated-result) - n=2 intentionally excludes "1x" values like "10" |
2361 | 2367 | 0 == strncmp(loader_disable_dynamic_library_unloading_env_var, "1", 2)) { |
2362 | 2368 | loader_disable_dynamic_library_unloading = true; |
2363 | 2369 | loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: library unloading is disabled"); |
@@ -2746,7 +2752,7 @@ void remove_all_non_valid_override_layers(struct loader_instance *inst, struct l |
2746 | 2752 | } |
2747 | 2753 | } else { |
2748 | 2754 | if (global_layer_index == -1) { |
2749 | | - global_layer_index = i; |
| 2755 | + global_layer_index = (int)i; |
2750 | 2756 | } else { |
2751 | 2757 | loader_log( |
2752 | 2758 | inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, |
@@ -2875,7 +2881,7 @@ VkResult loader_read_layer_json(const struct loader_instance *inst, struct loade |
2875 | 2881 | result = VK_ERROR_INITIALIZATION_FAILED; |
2876 | 2882 | goto out; |
2877 | 2883 | } |
2878 | | - props.info.implementationVersion = atoi(implementation_version); |
| 2884 | + props.info.implementationVersion = (uint32_t)strtoul(implementation_version, NULL, 10); |
2879 | 2885 |
|
2880 | 2886 | // Parse description |
2881 | 2887 |
|
@@ -3057,7 +3063,7 @@ VkResult loader_read_layer_json(const struct loader_instance *inst, struct loade |
3057 | 3063 | result = loader_parse_json_string(ext_item, "spec_version", &spec_version); |
3058 | 3064 | if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; |
3059 | 3065 | if (NULL != spec_version) { |
3060 | | - ext_prop.specVersion = atoi(spec_version); |
| 3066 | + ext_prop.specVersion = (uint32_t)strtoul(spec_version, NULL, 10); |
3061 | 3067 | } |
3062 | 3068 | loader_instance_heap_free(inst, spec_version); |
3063 | 3069 | bool ext_unsupported = wsi_unsupported_instance_extension(&ext_prop); |
@@ -3092,7 +3098,7 @@ VkResult loader_read_layer_json(const struct loader_instance *inst, struct loade |
3092 | 3098 | result = loader_parse_json_string(ext_item, "spec_version", &spec_version); |
3093 | 3099 | if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; |
3094 | 3100 | if (NULL != spec_version) { |
3095 | | - ext_prop.specVersion = atoi(spec_version); |
| 3101 | + ext_prop.specVersion = (uint32_t)strtoul(spec_version, NULL, 10); |
3096 | 3102 | } |
3097 | 3103 | loader_instance_heap_free(inst, spec_version); |
3098 | 3104 |
|
@@ -5010,7 +5016,7 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, c |
5010 | 5016 | } |
5011 | 5017 |
|
5012 | 5018 | // Create instance chain of enabled layers |
5013 | | - for (int32_t i = inst->expanded_activated_layer_list.count - 1; i >= 0; i--) { |
| 5019 | + for (int32_t i = (int32_t)inst->expanded_activated_layer_list.count - 1; i >= 0; i--) { |
5014 | 5020 | struct loader_layer_properties *layer_prop = inst->expanded_activated_layer_list.list[i]; |
5015 | 5021 | loader_platform_dl_handle lib_handle; |
5016 | 5022 |
|
@@ -5409,7 +5415,7 @@ VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCre |
5409 | 5415 | loader_create_info.pNext = &chain_info; |
5410 | 5416 |
|
5411 | 5417 | // Create instance chain of enabled layers |
5412 | | - for (int32_t i = inst->expanded_activated_layer_list.count - 1; i >= 0; i--) { |
| 5418 | + for (int32_t i = (int32_t)inst->expanded_activated_layer_list.count - 1; i >= 0; i--) { |
5413 | 5419 | struct loader_layer_properties *layer_prop = inst->expanded_activated_layer_list.list[i]; |
5414 | 5420 | loader_platform_dl_handle lib_handle = layer_prop->lib_handle; |
5415 | 5421 |
|
@@ -5666,7 +5672,7 @@ VkResult loader_validate_instance_extensions(struct loader_instance *inst, const |
5666 | 5672 |
|
5667 | 5673 | // Check if a user wants to disable the instance extension filtering behavior |
5668 | 5674 | env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst); |
5669 | | - if (NULL != env_value && atoi(env_value) != 0) { |
| 5675 | + if (NULL != env_value && strtol(env_value, NULL, 10) != 0) { |
5670 | 5676 | check_if_known = false; |
5671 | 5677 | } |
5672 | 5678 | loader_free_getenv(env_value, inst); |
@@ -5814,6 +5820,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI |
5814 | 5820 | // what the application requested, and thus will increase the instance version to a level that suites their needs. |
5815 | 5821 | if (pCreateInfo->pApplicationInfo && pCreateInfo->pApplicationInfo->apiVersion) { |
5816 | 5822 | loader_api_version altered_version = loader_make_version(pCreateInfo->pApplicationInfo->apiVersion); |
| 5823 | + // per LLP_LAYER_21 (docs/LoaderLayerInterface.md), a layer that clobbers pInstance before calling down is |
| 5824 | + // documented to crash the loader; this is not recoverable here. |
| 5825 | + // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) |
5817 | 5826 | if (altered_version.major != ptr_instance->app_api_version.major || |
5818 | 5827 | altered_version.minor != ptr_instance->app_api_version.minor) { |
5819 | 5828 | ptr_instance->app_api_version = altered_version; |
@@ -5848,12 +5857,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI |
5848 | 5857 | } else { |
5849 | 5858 | for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) { |
5850 | 5859 | if (!strcmp(pCreateInfo->ppEnabledExtensionNames[j], VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { |
| 5860 | + // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) - see LLP_LAYER_21 note above |
5851 | 5861 | ptr_instance->supports_get_dev_prop_2 = true; |
5852 | 5862 | break; |
5853 | 5863 | } |
5854 | 5864 | } |
5855 | 5865 | } |
5856 | 5866 |
|
| 5867 | + // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) - see LLP_LAYER_21 note above |
5857 | 5868 | for (uint32_t i = 0; i < ptr_instance->icd_tramp_list.count; i++) { |
5858 | 5869 | icd_term = loader_icd_add(ptr_instance, &ptr_instance->icd_tramp_list.scanned_list[i]); |
5859 | 5870 | if (NULL == icd_term) { |
@@ -6221,6 +6232,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(VkPhysicalDevice physical |
6221 | 6232 | dev, dev->loader_dispatch.core_dispatch.magic); |
6222 | 6233 | } |
6223 | 6234 |
|
| 6235 | + // per LLP_LAYER_22 (docs/LoaderLayerInterface.md), a layer that clobbers pDevice before calling down is |
| 6236 | + // documented to crash the loader; this is not recoverable here. |
| 6237 | + // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) |
6224 | 6238 | dev->phys_dev_term = phys_dev_term; |
6225 | 6239 |
|
6226 | 6240 | icd_exts.list = NULL; |
@@ -6599,7 +6613,7 @@ VkResult setup_loader_tramp_phys_devs(struct loader_instance *inst, uint32_t phy |
6599 | 6613 | for (uint32_t cur_idx = 0; cur_idx < old_count; ++cur_idx) { |
6600 | 6614 | if (old_to_new_index[cur_idx] == -1) { |
6601 | 6615 | new_phys_devs[new_idx] = inst->phys_devs_tramp[cur_idx]; |
6602 | | - old_to_new_index[cur_idx] = new_idx; |
| 6616 | + old_to_new_index[cur_idx] = (int32_t)new_idx; |
6603 | 6617 | found_count++; |
6604 | 6618 | break; |
6605 | 6619 | } |
@@ -6667,7 +6681,7 @@ bool is_linux_sort_enabled(struct loader_instance *inst) { |
6667 | 6681 | bool sort_items = inst->supports_get_dev_prop_2; |
6668 | 6682 | char *env_value = loader_getenv("VK_LOADER_DISABLE_SELECT", inst); |
6669 | 6683 | if (NULL != env_value) { |
6670 | | - int32_t int_env_val = atoi(env_value); |
| 6684 | + int32_t int_env_val = (int32_t)strtol(env_value, NULL, 10); |
6671 | 6685 | loader_free_getenv(env_value, inst); |
6672 | 6686 | if (int_env_val != 0) { |
6673 | 6687 | sort_items = false; |
@@ -7792,6 +7806,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups( |
7792 | 7806 |
|
7793 | 7807 | // Create a temporary array (on the stack) to keep track of the |
7794 | 7808 | // returned VkPhysicalDevice values. |
| 7809 | + // total_count may legitimately be 0 (no physical device groups); every subsequent use of local_phys_dev_groups |
| 7810 | + // is bounded by total_count, so a 0-byte alloca is never touched. |
| 7811 | + // NOLINTNEXTLINE(clang-analyzer-optin.portability.UnixAPI) |
7795 | 7812 | local_phys_dev_groups = loader_stack_alloc(sizeof(struct loader_physical_device_group_term) * total_count); |
7796 | 7813 | // Initialize the memory to something valid |
7797 | 7814 | memset(local_phys_dev_groups, 0, sizeof(struct loader_physical_device_group_term) * total_count); |
@@ -7912,6 +7929,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups( |
7912 | 7929 | icd_term->scanned_icd->lib_name); |
7913 | 7930 | goto out; |
7914 | 7931 | } |
| 7932 | + // Same guard as the other two paths above: the ICD can report a larger completed count here than it did |
| 7933 | + // during the counting pass. tmp_group_props and local_phys_dev_groups were both sized to the earlier |
| 7934 | + // (clamped) count_this_time, so trusting a larger value here would overflow both stack allocations. |
| 7935 | + if (count_this_time > total_count - cur_icd_group_count) { |
| 7936 | + count_this_time = total_count - cur_icd_group_count; |
| 7937 | + } |
7915 | 7938 | for (uint32_t group = 0; group < count_this_time; ++group) { |
7916 | 7939 | uint32_t cur_index = group + cur_icd_group_count; |
7917 | 7940 | local_phys_dev_groups[cur_index].group_props = tmp_group_props[group]; |
|
0 commit comments