mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-26 12:58:03 +00:00
BUG/MEDIUM: map/acl: pat_ref_{set,delete}_by_id regressions
Some regressions were introduced by5fea59754b
("MEDIUM: map/acl: Accelerate several functions using pat_ref_elt struct ->head list") pat_ref_delete_by_id() fails to properly unlink and free the removed reference because it bypasses the pat_ref_delete_by_ptr() made for that purpose. This function is normally used everywhere the target reference is set for removal, such as the pat_ref_delete() function that matches pattern against a string. The call was probably skipped by accident during the rewrite of the function. With the above commit also comes another undesirable change: both pat_ref_delete_by_id() and pat_ref_set_by_id() directly use the <refelt> argument as a valid pointer (they do dereference it). This is wrong, because <refelt> is unsafe and should be handled as an ID, not a pointer (hence the function name). Indeed, the calling function may directly pass user input from the CLI as <refelt> argument, so we must first ensure that it points to a valid element before using it, else it is probably invalid and we shouldn't touch it. What this patch essentially does, is that it reverts pat_ref_set_by_id() and pat_ref_delete_by_id() to pre5fea59754b
behavior. This seems like it was the only optimization from the patch that doesn't apply. Hopefully, after reviewing the changes with Fred, it seems that the 2 functions are only being involved in commands for manipulating maps or acls on the cli, so the "missed" opportunity to improve their performance shouldn't matter much. Nonetheless, if we wanted to speed up the reference lookup by ID, we could consider adding an eb64 tree for that specific purpose that contains all pattern references IDs (ie: pointers) so that eb lookup functions may be used instead of linear list search. The issue was raised by Marko Juraga as he failed to perform an an acl removal by reference on the CLI on 2.9 which was known to work properly on other versions. It should be backported on 2.9. Co-Authored-by: Frédéric Lécaille <flecaille@haproxy.com>
This commit is contained in:
parent
1a19e4e7af
commit
d7964c52ce
@ -1606,17 +1606,25 @@ void pat_ref_delete_by_ptr(struct pat_ref *ref, struct pat_ref_elt *elt)
|
||||
free(elt);
|
||||
}
|
||||
|
||||
/* This function removes all the patterns matching the pointer <refelt> from
|
||||
/* This function removes the pattern matching the pointer <refelt> from
|
||||
* the reference and from each expr member of this reference. This function
|
||||
* returns 1 if the entry was found and deleted, otherwise zero.
|
||||
*
|
||||
* <refelt> is user input: it is provided as an ID and should never be
|
||||
* dereferenced without making sure that it is valid.
|
||||
*/
|
||||
int pat_ref_delete_by_id(struct pat_ref *ref, struct pat_ref_elt *refelt)
|
||||
{
|
||||
int ret = !!refelt->node.node.leaf_p;
|
||||
struct pat_ref_elt *elt, *safe;
|
||||
|
||||
ebmb_delete(&refelt->node);
|
||||
|
||||
return ret;
|
||||
/* delete pattern from reference */
|
||||
list_for_each_entry_safe(elt, safe, &ref->head, list) {
|
||||
if (elt == refelt) {
|
||||
pat_ref_delete_by_ptr(ref, elt);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function removes all patterns matching <key> from the reference
|
||||
@ -1739,13 +1747,21 @@ static inline int pat_ref_set_elt(struct pat_ref *ref, struct pat_ref_elt *elt,
|
||||
/* This function modifies the sample of pat_ref_elt <refelt> in all expressions
|
||||
* found under <ref> to become <value>, after checking that <refelt> really
|
||||
* belongs to <ref>.
|
||||
*
|
||||
* <refelt> is user input: it is provided as an ID and should never be
|
||||
* dereferenced without making sure that it is valid.
|
||||
*/
|
||||
int pat_ref_set_by_id(struct pat_ref *ref, struct pat_ref_elt *refelt, const char *value, char **err)
|
||||
{
|
||||
if (refelt->node.node.leaf_p) {
|
||||
if (!pat_ref_set_elt(ref, refelt, value, err))
|
||||
return 0;
|
||||
return 1;
|
||||
struct pat_ref_elt *elt;
|
||||
|
||||
/* Look for pattern in the reference. */
|
||||
list_for_each_entry(elt, &ref->head, list) {
|
||||
if (elt == refelt) {
|
||||
if (!pat_ref_set_elt(ref, elt, value, err))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
memprintf(err, "key or pattern not found");
|
||||
|
Loading…
Reference in New Issue
Block a user