mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-10-29 05:40:27 -04:00 
			
		
		
		
	pod: Check that choices have enough values for their kind
Prevent out of bounds reads when a choice is too small for the type of choice that it is. Add a utility function to help catch this case.
This commit is contained in:
		
							parent
							
								
									5853e1150b
								
							
						
					
					
						commit
						fcfe01a0be
					
				
					 3 changed files with 26 additions and 2 deletions
				
			
		|  | @ -116,6 +116,27 @@ SPA_API_POD_BODY uint32_t spa_pod_type_align(uint32_t type) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | SPA_API_POD_BODY uint32_t spa_pod_choice_min_values(uint32_t choice_type) | ||||||
|  | { | ||||||
|  | 	switch (choice_type) { | ||||||
|  | 	case SPA_CHOICE_Enum: | ||||||
|  | 		return 2; | ||||||
|  | 	case SPA_CHOICE_Range: | ||||||
|  | 		return 3; | ||||||
|  | 	case SPA_CHOICE_Step: | ||||||
|  | 		return 4; | ||||||
|  | 	case SPA_CHOICE_None: | ||||||
|  | 	case SPA_CHOICE_Flags: | ||||||
|  | 	default: | ||||||
|  | 		/*
 | ||||||
|  | 		 * This must always return at least 1, because callers | ||||||
|  | 		 * assume that n_vals >= spa_pod_choice_min_values() | ||||||
|  | 		 * mean that n_vals is at least 1. | ||||||
|  | 		 */ | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| SPA_API_POD_BODY int spa_pod_body_from_data(void *data, size_t maxsize, off_t offset, size_t size, | SPA_API_POD_BODY int spa_pod_body_from_data(void *data, size_t maxsize, off_t offset, size_t size, | ||||||
| 		struct spa_pod *pod, const void **body) | 		struct spa_pod *pod, const void **body) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -226,6 +226,8 @@ SPA_API_POD_COMPARE int spa_pod_compare_is_in_range(uint32_t type, const void *v | ||||||
| SPA_API_POD_COMPARE int spa_pod_compare_is_valid_choice(uint32_t type, uint32_t size, | SPA_API_POD_COMPARE int spa_pod_compare_is_valid_choice(uint32_t type, uint32_t size, | ||||||
| 		const void *val, const void *vals, uint32_t n_vals, uint32_t choice) | 		const void *val, const void *vals, uint32_t n_vals, uint32_t choice) | ||||||
| { | { | ||||||
|  | 	if (n_vals < spa_pod_choice_min_values(choice)) | ||||||
|  | 		return 0; | ||||||
| 	switch (choice) { | 	switch (choice) { | ||||||
| 	case SPA_CHOICE_None: | 	case SPA_CHOICE_None: | ||||||
| 		if (spa_pod_compare_value(type, val, vals, size) == 0) | 		if (spa_pod_compare_value(type, val, vals, size) == 0) | ||||||
|  |  | ||||||
|  | @ -83,7 +83,8 @@ spa_pod_filter_prop(struct spa_pod_builder *b, | ||||||
| 	v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c); | 	v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c); | ||||||
| 
 | 
 | ||||||
| 	/* empty or bogus choices */ | 	/* empty or bogus choices */ | ||||||
| 	if (nalt1 < 1 || nalt2 < 1) | 	if (nalt1 < spa_pod_choice_min_values(p1c) || | ||||||
|  | 	    nalt2 < spa_pod_choice_min_values(p2c)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	alt1 = SPA_POD_BODY(v1); | 	alt1 = SPA_POD_BODY(v1); | ||||||
|  | @ -403,7 +404,7 @@ SPA_API_POD_FILTER int spa_pod_filter_object_make(struct spa_pod_object *pod) | ||||||
| 			struct spa_pod *v = spa_pod_get_values(&res->value, &nvals, &choice); | 			struct spa_pod *v = spa_pod_get_values(&res->value, &nvals, &choice); | ||||||
| 			const void *vals = SPA_POD_BODY(v); | 			const void *vals = SPA_POD_BODY(v); | ||||||
| 
 | 
 | ||||||
| 			if (nvals < 1) | 			if (nvals < spa_pod_choice_min_values(choice)) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			if (spa_pod_compare_is_valid_choice(v->type, v->size, | 			if (spa_pod_compare_is_valid_choice(v->type, v->size, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Demi Marie Obenour
						Demi Marie Obenour