mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	spa: add some more POD tests
Check if the pod size is at least big enough to hold 1 item when getting array or choice items. Check that the number of choice values is at least enough to handle the given choice type. Remove some redundant checks.
This commit is contained in:
		
							parent
							
								
									77a5100280
								
							
						
					
					
						commit
						95fb03c8e3
					
				
					 4 changed files with 30 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -164,8 +164,7 @@ SPA_API_DEBUG_FORMAT int spa_debugc_format(struct spa_debug_context *ctx, int in
 | 
			
		|||
		type = val->type;
 | 
			
		||||
		size = val->size;
 | 
			
		||||
 | 
			
		||||
		if (type < SPA_TYPE_None || type >= _SPA_TYPE_LAST || n_vals < 1 ||
 | 
			
		||||
		    size < spa_pod_type_size(type))
 | 
			
		||||
		if (type < SPA_TYPE_None || type >= _SPA_TYPE_LAST || n_vals < 1)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		vals = SPA_POD_BODY(val);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,6 +78,27 @@ SPA_API_POD_BODY uint32_t spa_pod_type_size(uint32_t type)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
		struct spa_pod *pod, const void **body)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -333,6 +354,8 @@ SPA_API_POD_BODY const void *spa_pod_array_body_get_values(const struct spa_pod_
 | 
			
		|||
	*n_values = child_size ? (arr->pod.size - sizeof(arr->body)) / child_size : 0;
 | 
			
		||||
	*val_size = child_size;
 | 
			
		||||
	*val_type = arr->body.child.type;
 | 
			
		||||
	if (*val_size < spa_pod_type_size(*val_type))
 | 
			
		||||
		*n_values = 0;
 | 
			
		||||
	return body;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -371,8 +394,9 @@ SPA_API_POD_BODY const void *spa_pod_choice_body_get_values(const struct spa_pod
 | 
			
		|||
	*val_type = pod->body.child.type;
 | 
			
		||||
	*n_values = child_size ? (pod->pod.size - sizeof(pod->body)) / child_size : 0;
 | 
			
		||||
	*choice = pod->body.type;
 | 
			
		||||
	if (*choice == SPA_CHOICE_None)
 | 
			
		||||
		*n_values = SPA_MIN(1u, *n_values);
 | 
			
		||||
	if (*n_values < spa_pod_choice_min_values(*choice) ||
 | 
			
		||||
	    *val_size < spa_pod_type_size(*val_type))
 | 
			
		||||
		*n_values = 0;
 | 
			
		||||
	return body;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ spa_pod_filter_prop(struct spa_pod_builder *b,
 | 
			
		|||
	v1 = spa_pod_get_values(&p1->value, &nalt1, &p1c);
 | 
			
		||||
	v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c);
 | 
			
		||||
 | 
			
		||||
	/* empty choices */
 | 
			
		||||
	/* empty/invalid choices */
 | 
			
		||||
	if (nalt1 < 1 || nalt2 < 1)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,8 +95,6 @@ spa_pod_filter_prop(struct spa_pod_builder *b,
 | 
			
		|||
	/* incompatible property types */
 | 
			
		||||
	if (type != v2->type || size != v2->size || p1->key != p2->key)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	if (size < spa_pod_type_size(type))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* start with copying the property */
 | 
			
		||||
	spa_pod_builder_prop(b, p1->key, p1->flags & p2->flags);
 | 
			
		||||
| 
						 | 
				
			
			@ -406,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);
 | 
			
		||||
			const void *vals = SPA_POD_BODY(v);
 | 
			
		||||
 | 
			
		||||
			if (v->size < spa_pod_type_size(v->type))
 | 
			
		||||
			if (nvals < 1)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (spa_pod_compare_is_valid_choice(v->type, v->size,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -228,7 +228,7 @@ SPA_API_POD_ITER struct spa_pod *spa_pod_get_values(const struct spa_pod *pod,
 | 
			
		|||
		spa_pod_choice_body_get_values(p, SPA_POD_BODY_CONST(p), n_vals, choice, &size, &type);
 | 
			
		||||
		return (struct spa_pod*)&p->body.child;
 | 
			
		||||
	} else {
 | 
			
		||||
		*n_vals = 1;
 | 
			
		||||
		*n_vals = pod->size < spa_pod_type_size(pod->type) ? 0 : 1;
 | 
			
		||||
		*choice = SPA_CHOICE_None;
 | 
			
		||||
		return (struct spa_pod*)pod;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue