/
githubmirror
/
xmlsec
Обзор
Документация
Войти
/
githubmirror
/
xmlsec
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/list.c
527 строк
15 KB
lsh123
(xmlsec-gnutls) Ensure that key cert is always the first one (#1192)
30 май 2026, 18:00
Не верифицирован
30 май 2026, 18:00
c2594d4
Код
Авторство
О чём код?
/** * XML Security Library (http://www.aleksey.com/xmlsec). * * This is free software; see the Copyright file in the source distribution for precise wording. * * Copyright (C) 2002-2026 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. */ /** * @addtogroup xmlsec_core_list * @brief Generic list structure functions. */ #include "globals.h" #include <stdlib.h> #include <string.h> #include <libxml/tree.h> #include <xmlsec/xmlsec.h> #include <xmlsec/list.h> #include <xmlsec/errors.h> #include "cast_helpers.h" static int xmlSecPtrListEnsureSize (xmlSecPtrListPtr list, xmlSecSize size); static xmlSecAllocMode gAllocMode = xmlSecAllocModeDouble; static xmlSecSize gInitialSize = 64; /** * @brief Sets the default allocation mode and initial list size. * @details Sets new default allocation mode and minimal initial list size. * @param defAllocMode the new default memory allocation mode. * @param defInitialSize the new default minimal initial size. */ void xmlSecPtrListSetDefaultAllocMode(xmlSecAllocMode defAllocMode, xmlSecSize defInitialSize) { xmlSecAssert(defInitialSize > 0); gAllocMode = defAllocMode; gInitialSize = defInitialSize; } /** * @brief Creates a new list object. * @details Creates new list object. Caller is responsible for freeing returned list * by calling #xmlSecPtrListDestroy function. * @param id the list klass. * @return pointer to newly allocated list or NULL if an error occurs. */ xmlSecPtrListPtr xmlSecPtrListCreate(xmlSecPtrListId id) { xmlSecPtrListPtr list; int ret; xmlSecAssert2(id != xmlSecPtrListIdUnknown, NULL); /* Allocate a new xmlSecPtrList and fill the fields. */ list = (xmlSecPtrListPtr)xmlMalloc(sizeof(xmlSecPtrList)); if(list == NULL) { xmlSecMallocError(sizeof(xmlSecPtrList), xmlSecPtrListKlassGetName(id)); return(NULL); } ret = xmlSecPtrListInitialize(list, id); if(ret < 0) { xmlSecInternalError("xmlSecPtrListInitialize", xmlSecPtrListKlassGetName(id)); xmlFree(list); return(NULL); } return(list); } /** * @brief Destroys a list object. * @details Destroys @p list created with #xmlSecPtrListCreate function. * @param list the pointer to list. */ void xmlSecPtrListDestroy(xmlSecPtrListPtr list) { xmlSecAssert(xmlSecPtrListIsValid(list)); xmlSecPtrListFinalize(list); xmlFree(list); } /** * @brief Initializes a list object. * @details Initializes the list of given klass. Caller is responsible * for cleaning up by calling #xmlSecPtrListFinalize function. * @param list the pointer to list. * @param id the list klass. * @return 0 on success or a negative value if an error occurs. */ int xmlSecPtrListInitialize(xmlSecPtrListPtr list, xmlSecPtrListId id) { xmlSecAssert2(id != xmlSecPtrListIdUnknown, -1); xmlSecAssert2(list != NULL, -1); memset(list, 0, sizeof(xmlSecPtrList)); list->id = id; list->allocMode = gAllocMode; return(0); } /** * @brief Cleans up a list object. * @details Cleans up the list initialized with #xmlSecPtrListInitialize function. * @param list the pointer to list. */ void xmlSecPtrListFinalize(xmlSecPtrListPtr list) { xmlSecAssert(xmlSecPtrListIsValid(list)); xmlSecPtrListEmpty(list); memset(list, 0, sizeof(xmlSecPtrList)); } /** * @brief Remove all items from @p list (if any). * @param list the pointer to list. */ void xmlSecPtrListEmpty(xmlSecPtrListPtr list) { xmlSecAssert(xmlSecPtrListIsValid(list)); if(list->id->destroyItem != NULL) { xmlSecSize pos; for(pos = 0; pos < list->use; ++pos) { xmlSecAssert(list->data != NULL); if(list->data[pos] != NULL) { list->id->destroyItem(list->data[pos]); } } } if(list->max > 0) { xmlSecAssert(list->data != NULL); memset(list->data, 0, sizeof(xmlSecPtr) * list->use); xmlFree(list->data); } list->max = list->use = 0; list->data = NULL; } /** * @brief Copies items from one list to another. * @details Copies @p src list items to @p dst list using duplicateItem method * of the list klass. If duplicateItem method is NULL then * we jsut copy pointers to items. * @param dst the pointer to destination list. * @param src the pointer to source list. * @return 0 on success or a negative value if an error occurs. */ int xmlSecPtrListCopy(xmlSecPtrListPtr dst, xmlSecPtrListPtr src) { xmlSecSize i; int ret; xmlSecAssert2(xmlSecPtrListIsValid(dst), -1); xmlSecAssert2(xmlSecPtrListIsValid(src), -1); xmlSecAssert2(dst->id == src->id, -1); /* allocate memory */ ret = xmlSecPtrListEnsureSize(dst, dst->use + src->use); if(ret < 0) { xmlSecInternalError2("xmlSecPtrListEnsureSize", xmlSecPtrListGetName(src), "size=" XMLSEC_SIZE_FMT, src->use); return(-1); } /* copy one item after another */ for(i = 0; i < src->use; ++i, ++dst->use) { xmlSecAssert2(src->data != NULL, -1); xmlSecAssert2(dst->data != NULL, -1); if((dst->id->duplicateItem != NULL) && (src->data[i] != NULL)) { dst->data[dst->use] = dst->id->duplicateItem(src->data[i]); if(dst->data[dst->use] == NULL) { xmlSecInternalError("duplicateItem", xmlSecPtrListGetName(src)); return(-1); } } else { dst->data[dst->use] = src->data[i]; } } return(0); } /** * @brief Creates a new copy of @p list and all its items. * @param list the pointer to list. * @return pointer to newly allocated list or NULL if an error occurs. */ xmlSecPtrListPtr xmlSecPtrListDuplicate(xmlSecPtrListPtr list) { xmlSecPtrListPtr newList; int ret; xmlSecAssert2(xmlSecPtrListIsValid(list), NULL); newList = xmlSecPtrListCreate(list->id); if(newList == NULL) { xmlSecInternalError("xmlSecPtrListCreate", xmlSecPtrListGetName(list)); return(NULL); } ret = xmlSecPtrListCopy(newList, list); if(ret < 0) { xmlSecInternalError("xmlSecPtrListCopy", xmlSecPtrListGetName(list)); xmlSecPtrListDestroy(newList); return(NULL); } return(newList); } /** * @brief Gets list size. * @param list the pointer to list. * @return the number of items in @p list. */ xmlSecSize xmlSecPtrListGetSize(xmlSecPtrListPtr list) { xmlSecAssert2(xmlSecPtrListIsValid(list), 0); return(list->use); } /** * @brief Gets item from the list. * @param list the pointer to list. * @param pos the item position. * @return the list item at position @p pos or NULL if @p pos is greater * than the number of items in the list or an error occurs. */ xmlSecPtr xmlSecPtrListGetItem(xmlSecPtrListPtr list, xmlSecSize pos) { xmlSecAssert2(xmlSecPtrListIsValid(list), NULL); xmlSecAssert2(list->data != NULL, NULL); xmlSecAssert2(pos < list->use, NULL); return(list->data[pos]); } /** * @brief Adds @p item to the end of the @p list. * @param list the pointer to list. * @param item the item. * @return 0 on success or a negative value if an error occurs. */ int xmlSecPtrListAdd(xmlSecPtrListPtr list, xmlSecPtr item) { int ret; xmlSecAssert2(xmlSecPtrListIsValid(list), -1); ret = xmlSecPtrListEnsureSize(list, list->use + 1); if(ret < 0) { xmlSecInternalError2("xmlSecPtrListEnsureSize", xmlSecPtrListGetName(list), "size=" XMLSEC_SIZE_FMT, list->use + 1); return(-1); } list->data[list->use++] = item; return(0); } /** * @brief Inserts an item at the given position. * @details Inserts @p item at the position @p pos in the @p list. * @param list the pointer to list. * @param item the item. * @param pos the position to insert at. * @return 0 on success or a negative value if an error occurs. */ int xmlSecPtrListInsert(xmlSecPtrListPtr list, xmlSecPtr item, xmlSecSize pos) { int ret; xmlSecAssert2(xmlSecPtrListIsValid(list), -1); ret = xmlSecPtrListEnsureSize(list, list->use + 1); if(ret < 0) { xmlSecInternalError2("xmlSecPtrListEnsureSize", xmlSecPtrListGetName(list), "size=" XMLSEC_SIZE_FMT, list->use + 1); return(-1); } if(pos < list->use) { /* move (pos, size) to (pos + 1, size + 1) and insert new item at pos */ memmove(&(list->data[pos + 1]), &(list->data[pos]), sizeof(xmlSecPtr) * (list->use - pos)); list->data[pos] = item; ++list->use; } else { /* insert at the end of the list if pos >= size */ list->data[list->use++] = item; } /* done */ return(0); } /** * @brief Sets a list item at the given position. * @details Sets the value of list item at position @p pos. The old value * is destroyed. * @param list the pointer to list. * @param item the item. * @param pos the pos. * @return 0 on success or a negative value if an error occurs. */ int xmlSecPtrListSet(xmlSecPtrListPtr list, xmlSecPtr item, xmlSecSize pos) { xmlSecAssert2(xmlSecPtrListIsValid(list), -1); xmlSecAssert2(list->data != NULL, -1); xmlSecAssert2(pos < list->use, -1); if((list->id->destroyItem != NULL) && (list->data[pos] != NULL)) { list->id->destroyItem(list->data[pos]); } list->data[pos] = item; return(0); } /** * @brief Destroys a list item at the given position. * @details Destroys list item at the position @p pos and shifts all following * items towards the beginning of the list. * @param list the pointer to list. * @param pos the position. * @return 0 on success or a negative value if an error occurs. */ int xmlSecPtrListRemove(xmlSecPtrListPtr list, xmlSecSize pos) { xmlSecAssert2(xmlSecPtrListIsValid(list), -1); xmlSecAssert2(list->data != NULL, -1); xmlSecAssert2(pos < list->use, -1); if((list->id->destroyItem != NULL) && (list->data[pos] != NULL)) { list->id->destroyItem(list->data[pos]); } if(pos < (list->use - 1)) { memmove(&(list->data[pos]), &(list->data[pos + 1]), sizeof(xmlSecPtr) * (list->use - pos - 1)); } --list->use; list->data[list->use] = NULL; return(0); } /** * @brief Removes and returns a list item. * @details Remove the list item at the position @p pos, shift all following * items towards the beginning of the list, and return the removed item back. * @param list the pointer to list. * @param pos the position. * @return the pointer to the list item. */ xmlSecPtr xmlSecPtrListRemoveAndReturn(xmlSecPtrListPtr list, xmlSecSize pos) { xmlSecPtr res; xmlSecAssert2(xmlSecPtrListIsValid(list), NULL); xmlSecAssert2(list->data != NULL, NULL); xmlSecAssert2(pos < list->use, NULL); res = list->data[pos]; if(pos < (list->use - 1)) { memmove(&(list->data[pos]), &(list->data[pos + 1]), sizeof(xmlSecPtr) * (list->use - pos - 1)); } --list->use; list->data[list->use] = NULL; return(res); } /** * @brief Removes and returns the last item from the list. * @param list the pointer to list. * @return the pointer to the last list item, or NULL if the list is empty. */ xmlSecPtr xmlSecPtrListPopLast(xmlSecPtrListPtr list) { xmlSecAssert2(xmlSecPtrListIsValid(list), NULL); if(list->use <= 0) { return(NULL); } return(xmlSecPtrListRemoveAndReturn(list, list->use - 1)); } /** * @brief Prints debug info about a list. * @details Prints debug information about @p list to the @p output. * @param list the pointer to list. * @param output the pointer to output FILE. */ void xmlSecPtrListDebugDump(xmlSecPtrListPtr list, FILE* output) { xmlSecAssert(xmlSecPtrListIsValid(list)); xmlSecAssert(output != NULL); fprintf(output, "=== list size: " XMLSEC_SIZE_FMT "\n", list->use); if(list->id->debugDumpItem != NULL) { xmlSecSize pos; for(pos = 0; pos < list->use; ++pos) { xmlSecAssert(list->data != NULL); if(list->data[pos] != NULL) { list->id->debugDumpItem(list->data[pos], output); } } } } /** * @brief Prints debug info about a list in XML format. * @details Prints debug information about @p list to the @p output in XML format. * @param list the pointer to list. * @param output the pointer to output FILE. */ void xmlSecPtrListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) { xmlSecAssert(xmlSecPtrListIsValid(list)); xmlSecAssert(output != NULL); fprintf(output, "<List size=\"" XMLSEC_SIZE_FMT "\">\n", list->use); if(list->id->debugXmlDumpItem != NULL) { xmlSecSize pos; for(pos = 0; pos < list->use; ++pos) { xmlSecAssert(list->data != NULL); if(list->data[pos] != NULL) { list->id->debugXmlDumpItem(list->data[pos], output); } } } fprintf(output, "</List>\n"); } static int xmlSecPtrListEnsureSize(xmlSecPtrListPtr list, xmlSecSize size) { xmlSecPtr* newData; xmlSecSize newSize = 0; xmlSecAssert2(xmlSecPtrListIsValid(list), -1); if(size < list->max) { return(0); } switch(list->allocMode) { case xmlSecAllocModeExact: newSize = size + 8; break; case xmlSecAllocModeDouble: newSize = 2 * size + 32; break; } if(newSize < gInitialSize) { newSize = gInitialSize; } if(list->data != NULL) { newData = (xmlSecPtr*)xmlRealloc(list->data, sizeof(xmlSecPtr) * newSize); } else { newData = (xmlSecPtr*)xmlMalloc(sizeof(xmlSecPtr) * newSize); } if(newData == NULL) { xmlSecMallocError(sizeof(xmlSecPtr) * newSize, xmlSecPtrListGetName(list)); return(-1); } list->data = newData; list->max = newSize; return(0); } /****************************************************************************** * * strings list * *****************************************************************************/ static xmlSecPtr xmlSecStringListDuplicateItem (xmlSecPtr ptr); static void xmlSecStringListDestroyItem (xmlSecPtr ptr); static xmlSecPtrListKlass xmlSecStringListKlass = { BAD_CAST "strings-list", xmlSecStringListDuplicateItem, /* xmlSecPtrDuplicateItemMethod duplicateItem; */ xmlSecStringListDestroyItem, /* xmlSecPtrDestroyItemMethod destroyItem; */ NULL, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */ NULL, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */ }; /** * @brief The strings list class. * @return strings list klass. */ xmlSecPtrListId xmlSecStringListGetKlass(void) { return(&xmlSecStringListKlass); } static xmlSecPtr xmlSecStringListDuplicateItem(xmlSecPtr ptr) { xmlSecAssert2(ptr != NULL, NULL); return(xmlStrdup((xmlChar*)ptr)); } static void xmlSecStringListDestroyItem(xmlSecPtr ptr) { xmlSecAssert(ptr != NULL); xmlFree(ptr); }