[File] Possible ABI break when updating file from 5.33 to 5.35
Christos Zoulas
christos at zoulas.com
Sat Jan 26 19:04:35 UTC 2019
Hi,
Although those changes look scary, there is nothing to be concerned about:
1. the functions missing are not part of the ABI (and programs should not be using them)
2. the magic_set structure is not exposed in the ABI.
The only thing you need to make sure is that the magic database and the magic library are
consistent...
christos
> On Jan 26, 2019, at 11:14 AM, <emersonbernier at tutanota.com> <emersonbernier at tutanota.com> wrote:
>
> Hi!
>
> In freedesktop-sdk[1] we're trying to keep ABI compatibility when updating
> elements like file to new releases. In order to achieve this we use libabigail[2]
> tool to automate ABI compat checks. During update file from 5.33 to 5.35 (we
> missed 5.34 release) our tool produced following complaint:
>
> ╔════════════════╗
> ║ Comparing ABIs ║
> ╚════════════════╝
>
> ┌───────────────────────────────────┐
> │ ABI Break: libmagic.so.1:libmagic │
> └───────────────────────────────────┘
>
> Functions changes summary: 86 Removed, 1 Changed (15 filtered out), 0 Added functions
> Variables changes summary: 4 Removed, 0 Changed, 0 Added variables
>
> 86 Removed functions:
>
> 'function int buffer_apprentice(magic_set*, magic**, size_t*, size_t)' {buffer_apprentice}
> 'function int buffer_fill(const buffer*)' {buffer_fill}
> 'function void buffer_fini(buffer*)' {buffer_fini}
> 'function void buffer_init(buffer*, int, void*, size_t)' {buffer_init}
> 'function size_t cdf_count_chain(const cdf_sat_t*, cdf_secid_t, size_t)' {cdf_count_chain}
> 'function char* cdf_ctime(const time_t*, char*)' {cdf_ctime}
> 'function int cdf_find_stream(const cdf_dir_t*, const char*, int)' {cdf_find_stream}
> 'function int cdf_print_classid(char*, size_t, const cdf_classid_t*)' {cdf_print_classid}
> 'function int cdf_print_elapsed_time(char*, size_t, cdf_timestamp_t)' {cdf_print_elapsed_time}
> 'function int cdf_print_property_name(char*, size_t, uint32_t)' {cdf_print_property_name}
> 'function int cdf_read_dir(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, cdf_dir_t*)' {cdf_read_dir}
> 'function int cdf_read_doc_summary_info(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_sat_t*, const cdf_stream_t*, const cdf_dir_t*, cdf_stream_t*)' {cdf_read_doc_summary_info}
> 'function int cdf_read_header(const cdf_info_t*, cdf_header_t*)' {cdf_read_header}
> 'function int cdf_read_long_sector_chain(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, cdf_secid_t, size_t, cdf_stream_t*)' {cdf_read_long_sector_chain}
> 'function int cdf_read_property_info(const cdf_stream_t*, const cdf_header_t*, uint32_t, cdf_property_info_t**, size_t*, size_t*)' {cdf_read_property_info}
> 'function int cdf_read_sat(const cdf_info_t*, cdf_header_t*, cdf_sat_t*)' {cdf_read_sat}
> 'function ssize_t cdf_read_sector(const cdf_info_t*, void*, size_t, size_t, const cdf_header_t*, cdf_secid_t)' {cdf_read_sector}
> 'function int cdf_read_sector_chain(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_sat_t*, const cdf_stream_t*, cdf_secid_t, size_t, cdf_stream_t*)' {cdf_read_sector_chain}
> 'function ssize_t cdf_read_short_sector(const cdf_stream_t*, void*, size_t, size_t, const cdf_header_t*, cdf_secid_t)' {cdf_read_short_sector}
> 'function int cdf_read_short_sector_chain(const cdf_header_t*, const cdf_sat_t*, const cdf_stream_t*, cdf_secid_t, size_t, cdf_stream_t*)' {cdf_read_short_sector_chain}
> 'function int cdf_read_short_stream(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_dir_t*, cdf_stream_t*, const cdf_directory_t**)' {cdf_read_short_stream}
> 'function int cdf_read_ssat(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, cdf_sat_t*)' {cdf_read_ssat}
> 'function int cdf_read_summary_info(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_sat_t*, const cdf_stream_t*, const cdf_dir_t*, cdf_stream_t*)' {cdf_read_summary_info}
> 'function int cdf_read_user_stream(const cdf_info_t*, const cdf_header_t*, const cdf_sat_t*, const cdf_sat_t*, const cdf_stream_t*, const cdf_dir_t*, const char*, cdf_stream_t*)' {cdf_read_user_stream}
> 'function void cdf_swap_class(cdf_classid_t*)' {cdf_swap_class}
> 'function void cdf_swap_dir(cdf_directory_t*)' {cdf_swap_dir}
> 'function void cdf_swap_header(cdf_header_t*)' {cdf_swap_header}
> 'function int cdf_timespec_to_timestamp(cdf_timestamp_t*, const timespec*)' {cdf_timespec_to_timestamp}
> 'function int cdf_timestamp_to_timespec(timespec*, cdf_timestamp_t)' {cdf_timestamp_to_timespec}
> 'function uint16_t cdf_tole2(uint16_t)' {cdf_tole2}
> 'function uint32_t cdf_tole4(uint32_t)' {cdf_tole4}
> 'function uint64_t cdf_tole8(uint64_t)' {cdf_tole8}
> 'function char* cdf_u16tos8(char*, size_t, const uint16_t*)' {cdf_u16tos8}
> 'function int cdf_unpack_catalog(const cdf_header_t*, const cdf_stream_t*, cdf_catalog_t**)' {cdf_unpack_catalog}
> 'function void cdf_unpack_dir(cdf_directory_t*, char*)' {cdf_unpack_dir}
> 'function void cdf_unpack_header(cdf_header_t*, char*)' {cdf_unpack_header}
> 'function int cdf_unpack_summary_info(const cdf_stream_t*, const cdf_header_t*, cdf_summary_info_header_t*, cdf_property_info_t**, size_t*)' {cdf_unpack_summary_info}
> 'function int cdf_zero_stream(cdf_stream_t*)' {cdf_zero_stream}
> 'function int der_cmp(magic_set*, magic*)' {der_cmp}
> 'function int32_t der_offs(magic_set*, magic*, size_t)' {der_offs}
> 'function int file_apprentice(magic_set*, const char*, int)' {file_apprentice}
> 'function int file_ascmagic(magic_set*, const buffer*, int)' {file_ascmagic}
> 'function int file_ascmagic_with_encoding(magic_set*, const buffer*, unichar*, size_t, const char*, const char*, int)' {file_ascmagic_with_encoding}
> 'function void file_badread(magic_set*)' {file_badread}
> 'function void file_badseek(magic_set*)' {file_badseek}
> 'function int file_buffer(magic_set*, int, const char*, void*, size_t)' {file_buffer}
> 'function int file_check_mem(magic_set*, unsigned int)' {file_check_mem}
> 'function int file_encoding(magic_set*, const buffer*, unichar**, size_t*, const char**, const char**, const char**)' {file_encoding}
> 'function void file_error(magic_set*, int, const char*, ...)' {file_error}
> 'function const char* file_fmttime(uint64_t, int, char*)' {file_fmttime}
> 'function int file_fsmagic(magic_set*, const char*, stat*)' {file_fsmagic}
> 'function const char* file_getbuffer(magic_set*)' {file_getbuffer}
> 'function int file_is_tar(magic_set*, const buffer*)' {file_is_tar}
> 'function int file_looks_utf8(const unsigned char*, size_t, unichar*, size_t*)' {file_looks_utf8}
> 'function void file_magerror(magic_set*, const char*, ...)' {file_magerror}
> 'function int file_magicfind(magic_set*, const char*, mlist*)' {file_magicfind}
> 'function void file_magwarn(magic_set*, const char*, ...)' {file_magwarn}
> 'function void file_mdump(magic*)' {file_mdump}
> 'function magic_set* file_ms_alloc(int)' {file_ms_alloc}
> 'function void file_ms_free(magic_set*)' {file_ms_free}
> 'function void file_oomem(magic_set*, size_t)' {file_oomem}
> 'function int file_pipe2file(magic_set*, int, void*, size_t)' {file_pipe2file}
> 'function char* file_pop_buffer(magic_set*, file_pushbuf_t*)' {file_pop_buffer}
> 'function char* file_printable(char*, size_t, const char*)' {file_printable}
> 'function size_t file_printedlen(const magic_set*)' {file_printedlen}
> 'function int file_printf(magic_set*, const char*, ...)' {file_printf}
> 'function size_t file_pstring_get_length(const magic*, const char*)' {file_pstring_get_length}
> 'function size_t file_pstring_length_size(const magic*)' {file_pstring_length_size}
> 'function file_pushbuf_t* file_push_buffer(magic_set*)' {file_push_buffer}
> 'function int file_regcomp(file_regex_t*, const char*, int)' {file_regcomp}
> 'function void file_regerror(file_regex_t*, int, magic_set*)' {file_regerror}
> 'function int file_regexec(file_regex_t*, const char*, size_t, regmatch_t*, int)' {file_regexec}
> 'function void file_regfree(file_regex_t*)' {file_regfree}
> 'function int file_replace(magic_set*, const char*, const char*)' {file_replace}
> 'function int file_reset(magic_set*, int)' {file_reset}
> 'function void file_showstr(FILE*, const char*, size_t)' {file_showstr}
> 'function uint64_t file_signextend(magic_set*, magic*, uint64_t)' {file_signextend}
> 'function int file_softmagic(magic_set*, const buffer*, uint16_t*, uint16_t*, int, int)' {file_softmagic}
> 'function int file_trycdf(magic_set*, const buffer*)' {file_trycdf}
> 'function int file_tryelf(magic_set*, const buffer*)' {file_tryelf}
> 'function int file_vprintf(magic_set*, const char*, __va_list_tag*)' {file_vprintf}
> 'function int file_zmagic(magic_set*, const buffer*, const char*)' {file_zmagic}
> 'function const char* fmtcheck(const char*, const char*)' {fmtcheck}
> 'function ssize_t sread(int, void*, size_t, int)' {sread}
> 'function size_t strlcat(char*, const char*, size_t)' {strlcat}
> 'function size_t strlcpy(char*, const char*, size_t)' {strlcpy}
>
> 1 function with some indirect sub-type change:
>
> [C]'function const char* magic_buffer(magic_set*, void*, size_t)' at magic.c:524:1 has some indirect sub-type changes:
> parameter 1 of type 'magic_set*' has sub-type changes:
> in pointed to type 'struct magic_set' at file.h:400:1:
> type size changed from 1920 to 1984 (in bits)
> 1 data member insertion:
> 'mode_t magic_set::mode', at offset 704 (in bits) at file.h:419:1
> 9 data member changes:
> 'struct {const char* s; size_t s_len; size_t offset; size_t rm_len;} magic_set::search' offset changed from 704 to 768 (in bits) (by +64 bits)
> 'VALUETYPE magic_set::ms_value' offset changed from 960 to 1024 (in bits) (by +64 bits)
> 'uint16_t magic_set::indir_max' offset changed from 1728 to 1792 (in bits) (by +64 bits)
> 'uint16_t magic_set::name_max' offset changed from 1744 to 1808 (in bits) (by +64 bits)
> 'uint16_t magic_set::elf_shnum_max' offset changed from 1760 to 1824 (in bits) (by +64 bits)
> 'uint16_t magic_set::elf_phnum_max' offset changed from 1776 to 1840 (in bits) (by +64 bits)
> 'uint16_t magic_set::elf_notes_max' offset changed from 1792 to 1856 (in bits) (by +64 bits)
> 'uint16_t magic_set::regex_max' offset changed from 1808 to 1872 (in bits) (by +64 bits)
> 'size_t magic_set::bytes_max' offset changed from 1856 to 1920 (in bits) (by +64 bits)
>
>
> 4 Removed variables:
>
> 'int file_formats[49]' {file_formats}
> 'const char* file_names[]' {file_names}
> 'const size_t file_nformats' {file_nformats}
> 'const size_t file_nnames' {file_nnames}
>
> As part of our discussion[3] about what to do with that we would like to ask
> about your opinion on the matter. Especially I wanted to ask if reported changes
> were intentional and if they're safe for backward compatibility thus if above
> report is a false positive. I would be grateful if you can find time to respond.
> Thank you.
>
> [1] https://gitlab.com/freedesktop-sdk <https://gitlab.com/freedesktop-sdk>
> [2] https://sourceware.org/libabigail <https://sourceware.org/libabigail>
> [3] https://gitlab.com/freedesktop-sdk/freedesktop-sdk/merge_requests/900 <https://gitlab.com/freedesktop-sdk/freedesktop-sdk/merge_requests/900>
>
> --
> File mailing list
> File at astron.com
> https://mailman.astron.com/mailman/listinfo/file
More information about the File
mailing list