зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1691347 - Work around a null argument bug in _platform_strstr in CUPS. r=dholbert
This is just a large conditional to check for the specific branches taken that would result in the null string. The path in CUPS is as follows: In cupsCopyDestInfo, CUPS_DEST_FLAG_DEVICE is set when the connection is not null (same as CUPS_HTTP_DEFAULT), the print server is not the same as our hostname and is not path-based (starts with a '/'), or the IPP port is different than the global server IPP port.c9da6f63b2/cups/dest-options.c (L718-L722)
In _cupsGetDestResource, CUPS fetches the IPP options "printer-uri-supported" and "device-uri". Importantly, IPP options are returned as null when missing.23c45db76a/cups/dest.c (L1138-L1141)
If the CUPS_DEST_FLAG_DEVICE is set or the "printer-uri-supported" option is not set, CUPS checks for "._tcp" in the "device-uri" option without doing a NULL-check first.23c45db76a/cups/dest.c (L1144)
If we find that those branches will be taken, don't actually fetch the CUPS data and instead just return an empty printer info. Differential Revision: https://phabricator.services.mozilla.com/D128529
This commit is contained in:
Родитель
d5dbd9115b
Коммит
c286431b9a
|
@ -58,14 +58,19 @@ class nsCUPSShim {
|
|||
X(Optional::No, cupsGetDests) \
|
||||
X(Optional::No, cupsGetNamedDest) \
|
||||
X(Optional::No, cupsGetOption) \
|
||||
X(Optional::No, cupsServer) \
|
||||
X(Optional::Yes, httpAddrPort) \
|
||||
X(Optional::No, httpClose) \
|
||||
X(Optional::No, httpGetHostname) \
|
||||
X(Optional::Yes, httpGetAddress) \
|
||||
X(Optional::No, ippAddString) \
|
||||
X(Optional::No, ippAddStrings) \
|
||||
X(Optional::No, ippDelete) \
|
||||
X(Optional::No, ippFindAttribute) \
|
||||
X(Optional::No, ippGetCount) \
|
||||
X(Optional::No, ippGetString) \
|
||||
X(Optional::No, ippNewRequest)
|
||||
X(Optional::No, ippNewRequest) \
|
||||
X(Optional::No, ippPort)
|
||||
|
||||
#ifdef CUPS_SHIM_RUNTIME_LINK
|
||||
// Define a single field which holds a function pointer.
|
||||
|
|
|
@ -149,8 +149,7 @@ bool nsPrinterCUPS::SupportsColor() const {
|
|||
|
||||
bool nsPrinterCUPS::SupportsCollation() const {
|
||||
// We can't depend on cupsGetIntegerOption existing.
|
||||
const char* const value = mShim.cupsGetOption(
|
||||
"printer-type", mPrinter->num_options, mPrinter->options);
|
||||
const char* const value = FindCUPSOption("printer-type");
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
@ -350,6 +349,77 @@ nsPrinterCUPS::PrinterInfoLock nsPrinterCUPS::TryEnsurePrinterInfo(
|
|||
lock->mTriedInitWithConnection = true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mPrinter);
|
||||
|
||||
// httpGetAddress was only added in CUPS 2.0, and some systems still use
|
||||
// CUPS 1.7.
|
||||
if (aConnection && MOZ_LIKELY(mShim.httpGetAddress && mShim.httpAddrPort)) {
|
||||
// This is a workaround for the CUPS Bug seen in bug 1691347.
|
||||
// This is to avoid a null string being passed to strstr in CUPS. The path
|
||||
// in CUPS that leads to this is as follows:
|
||||
//
|
||||
// In cupsCopyDestInfo, CUPS_DEST_FLAG_DEVICE is set when the connection is
|
||||
// not null (same as CUPS_HTTP_DEFAULT), the print server is not the same
|
||||
// as our hostname and is not path-based (starts with a '/'), or the IPP
|
||||
// port is different than the global server IPP port.
|
||||
//
|
||||
// https://github.com/apple/cups/blob/c9da6f63b263faef5d50592fe8cf8056e0a58aa2/cups/dest-options.c#L718-L722
|
||||
//
|
||||
// In _cupsGetDestResource, CUPS fetches the IPP options "device-uri" and
|
||||
// "printer-uri-supported". Note that IPP options are returned as null when
|
||||
// missing.
|
||||
//
|
||||
// https://github.com/apple/cups/blob/23c45db76a8520fd6c3b1d9164dbe312f1ab1481/cups/dest.c#L1138-L1141
|
||||
//
|
||||
// If the CUPS_DEST_FLAG_DEVICE is set or the "printer-uri-supported"
|
||||
// option is not set, CUPS checks for "._tcp" in the "device-uri" option
|
||||
// without doing a NULL-check first.
|
||||
//
|
||||
// https://github.com/apple/cups/blob/23c45db76a8520fd6c3b1d9164dbe312f1ab1481/cups/dest.c#L1144
|
||||
//
|
||||
// If we find that those branches will be taken, don't actually fetch the
|
||||
// CUPS data and instead just return an empty printer info.
|
||||
|
||||
const char* const serverNameBytes = mShim.cupsServer();
|
||||
|
||||
if (MOZ_LIKELY(serverNameBytes)) {
|
||||
const nsDependentCString serverName{serverNameBytes};
|
||||
|
||||
// We only need enough characters to determine equality with serverName.
|
||||
// + 2 because we need one byte for the null-character, and we also want
|
||||
// to get more characters of the host name than the server name if
|
||||
// possible. Otherwise, if the hostname starts with the same text as the
|
||||
// entire server name, it would compare equal when it's not.
|
||||
const size_t hostnameMemLength = serverName.Length() + 2;
|
||||
auto hostnameMem = MakeUnique<char[]>(hostnameMemLength);
|
||||
|
||||
// We don't expect httpGetHostname to return null when a connection is
|
||||
// passed, but it's better not to make assumptions.
|
||||
const char* const hostnameBytes = mShim.httpGetHostname(
|
||||
aConnection, hostnameMem.get(), hostnameMemLength);
|
||||
|
||||
if (MOZ_LIKELY(hostnameBytes)) {
|
||||
const nsDependentCString hostname{hostnameBytes};
|
||||
|
||||
// Match the condional at
|
||||
// https://github.com/apple/cups/blob/c9da6f63b263faef5d50592fe8cf8056e0a58aa2/cups/dest-options.c#L718
|
||||
const bool portsDiffer =
|
||||
mShim.httpAddrPort(mShim.httpGetAddress(aConnection)) !=
|
||||
mShim.ippPort();
|
||||
const bool cupsDestDeviceFlag =
|
||||
(hostname != serverName && serverName[0] != '/') || portsDiffer;
|
||||
|
||||
// Match the conditional at
|
||||
// https://github.com/apple/cups/blob/23c45db76a8520fd6c3b1d9164dbe312f1ab1481/cups/dest.c#L1144
|
||||
// but if device-uri is null do not call into CUPS.
|
||||
if ((cupsDestDeviceFlag || !FindCUPSOption("printer-uri-supported")) &&
|
||||
!FindCUPSOption("device-uri")) {
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All CUPS calls that take the printer info do null-checks internally, so we
|
||||
// can fetch this info and only worry about the result of the later CUPS
|
||||
// functions.
|
||||
|
|
|
@ -48,6 +48,10 @@ class nsPrinterCUPS final : public nsPrinterBase {
|
|||
static void ForEachExtraMonochromeSetting(
|
||||
mozilla::FunctionRef<void(const nsACString&, const nsACString&)>);
|
||||
|
||||
inline const char* FindCUPSOption(const char* name) const {
|
||||
return mShim.cupsGetOption(name, mPrinter->num_options, mPrinter->options);
|
||||
}
|
||||
|
||||
private:
|
||||
struct CUPSPrinterInfo {
|
||||
cups_dinfo_t* mPrinterInfo = nullptr;
|
||||
|
|
Загрузка…
Ссылка в новой задаче