← Commit list

e2c5cc042

Denys Vlasenko
Denys Vlasenko
2026-09-21
SUCCESS Duration: 236s

Subject

dpkg: free results of read_package_field(), preliminary cleanups in read_package_field()

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

archival/dpkg.c+45 -35
@@ -531,26 +531,31 @@ static void free_package(common_node_t *node)
}
/*
- * Gets the next package field from package_buffer, separated into the field name
- * and field value, it returns the int offset to the first character of the next field
+ * Gets the next package field from package_buffer:
+ * "Name:<whitespace>VALUE{\n|NUL}"
+ * "Name:<whitespace>\n
+ * " VALUE{\n|NUL}"
+ * separated into "NAME" and "VALUE", both strdup()ed.
+ * Returns the int offset to the first character of the next field.
+ * The package_buffer parameter is NUL-terminated.
*/
static int read_package_field(const char *package_buffer, char **field_name, char **field_value)
{
int offset_name_start = 0;
int offset_name_end = 0;
int offset_value_start = 0;
- int offset_value_end = 0;
int offset = 0;
int next_offset;
int name_length;
int value_length;
int exit_flag = FALSE;
+ *field_name = NULL;
+ *field_value = NULL;
if (package_buffer == NULL) {
- *field_name = NULL;
- *field_value = NULL;
return -1;
}
+
while (1) {
next_offset = offset + 1;
switch (package_buffer[offset]) {
@@ -566,14 +571,14 @@ static int read_package_field(const char *package_buffer, char **field_name, cha
* immediately after name */
break;
case '\n':
- /* TODO: The char next_offset may be out of bounds */
if (package_buffer[next_offset] != ' ') {
exit_flag = TRUE;
break;
}
+ /* fall through */
case '\t':
case ' ':
- /* increment the value start point if its a just filler */
+ /* increment start points if it is just a filler */
if (offset_name_start == offset) {
offset_name_start++;
}
@@ -584,9 +589,8 @@ static int read_package_field(const char *package_buffer, char **field_name, cha
}
if (exit_flag) {
/* Check that the names are valid */
- offset_value_end = offset;
name_length = offset_name_end - offset_name_start;
- value_length = offset_value_end - offset_value_start;
+ value_length = offset - offset_value_start;
if (name_length == 0) {
break;
}
@@ -594,27 +598,26 @@ static int read_package_field(const char *package_buffer, char **field_name, cha
break;
}
- /* If not valid, start fresh with next field */
+ /* Not valid: start fresh with next field */
exit_flag = FALSE;
offset_name_start = offset + 1;
offset_name_end = 0;
offset_value_start = offset + 1;
- offset_value_end = offset + 1;
offset++;
}
offset++;
- }
- *field_name = NULL;
- if (name_length) {
+ } /* while (1) */
+
+ if (name_length > 0) {
*field_name = xstrndup(&package_buffer[offset_name_start], name_length);
}
- *field_value = NULL;
if (value_length > 0) {
*field_value = xstrndup(&package_buffer[offset_value_start], value_length);
}
return next_offset;
}
+/* The parameter is NUL-terminated */
static unsigned fill_package_struct(char *control_buffer)
{
static const char field_names[] ALIGN1 =
@@ -623,14 +626,14 @@ static unsigned fill_package_struct(char *control_buffer)
"Conflicts\0""Suggests\0""Recommends\0""Enhances\0";
common_node_t *new_node = xzalloc(sizeof(common_node_t));
- char *field_name;
- char *field_value;
int field_start = 0;
- int num = -1;
int buffer_length = strlen(control_buffer);
+ int num;
new_node->version = search_name_hashtable("unknown");
while (field_start < buffer_length) {
+ char *field_name;
+ char *field_value;
unsigned field_num;
field_start += read_package_field(&control_buffer[field_start],
@@ -799,7 +802,7 @@ static void write_buffer_no_status(FILE *new_status_file, const char *control_bu
char *name;
char *value;
int start = 0;
- while (1) {
+ while (control_buffer[start]) {
start += read_package_field(&control_buffer[start], &name, &value);
if (name == NULL) {
break;
@@ -807,6 +810,8 @@ static void write_buffer_no_status(FILE *new_status_file, const char *control_bu
if (strcmp(name, "Status") != 0) {
fprintf(new_status_file, "%s: %s\n", name, value);
}
+ free(name);
+ free(value);
}
}
@@ -815,34 +820,35 @@ static void write_status_file(deb_file_t **deb_file)
{
FILE *old_status_file = xfopen_for_read("/var/lib/dpkg/status");
FILE *new_status_file = xfopen_for_write("/var/lib/dpkg/status.udeb");
- char *package_name;
- char *status_from_file;
- char *control_buffer = NULL;
- char *tmp_string;
- int status_num;
+ char *control_buffer;
int field_start = 0;
- int write_flag;
- int i = 0;
+ int status_num;
+ int i;
/* Update previously known packages */
while ((control_buffer = xmalloc_fgetline_str(old_status_file, "\n\n")) != NULL) {
+ char *package_name;
+ char *status_from_file;
+ char *tmp_string;
+ int write_flag;
+//FIXME: "int field_start = 0;" should be _here_, right?
+
tmp_string = strstr(control_buffer, "Package:");
if (tmp_string == NULL) {
+ free(control_buffer);
continue;
}
-
tmp_string += 8;
tmp_string += strspn(tmp_string, " \n\t");
package_name = xstrndup(tmp_string, strcspn(tmp_string, "\n"));
+
write_flag = FALSE;
+ status_from_file = NULL;
tmp_string = strstr(control_buffer, "Status:");
if (tmp_string != NULL) {
- /* Separate the status value from the control buffer */
tmp_string += 7;
tmp_string += strspn(tmp_string, " \n\t");
status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n"));
- } else {
- status_from_file = NULL;
}
/* Find this package in the status hashtable */
@@ -870,7 +876,7 @@ static void write_status_file(deb_file_t **deb_file)
}
i++;
}
- /* This is temperary, debugging only */
+ /* This is temporary, debugging only */
if (deb_file[i] == NULL) {
bb_error_msg_and_die("ALERT: cannot find a control file, "
"your status file may be broken, status may be "
@@ -882,7 +888,7 @@ static void write_status_file(deb_file_t **deb_file)
fprintf(new_status_file, "Package: %s\n", package_name);
fprintf(new_status_file, "Status: %s\n", status_from_hashtable);
- while (1) {
+ while (control_buffer[field_start]) {
char *field_name;
char *field_value;
field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
@@ -894,13 +900,15 @@ static void write_status_file(deb_file_t **deb_file)
) {
fprintf(new_status_file, "%s: %s\n", field_name, field_value);
}
+ free(field_name);
+ free(field_value);
}
write_flag = TRUE;
fputs("\n", new_status_file);
}
else if (strcmp("config-files", name_hashtable[state_status]) == 0) {
/* only change the status line */
- while (1) {
+ while (control_buffer[field_start]) {
char *field_name;
char *field_value;
field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
@@ -913,13 +921,15 @@ static void write_status_file(deb_file_t **deb_file)
} else {
fprintf(new_status_file, "%s: %s\n", field_name, field_value);
}
+ free(field_name);
+ free(field_value);
}
write_flag = TRUE;
fputs("\n", new_status_file);
}
}
}
- /* If the package from the status file wasn't handle above, do it now*/
+ /* If the package from the status file wasn't handled above, do it now */
if (!write_flag) {
fprintf(new_status_file, "%s\n\n", control_buffer);
}
@@ -927,7 +937,7 @@ static void write_status_file(deb_file_t **deb_file)
free(status_from_file);
free(package_name);
free(control_buffer);
- }
+ } /* while (control_buffer) */
/* Write any new packages */
for (i = 0; deb_file[i] != NULL; i++) {