free (c->url);
c->url = NULL;
+ /* PR 27982: Add max size if DEBUGINFOD_MAXSIZE is set. */
+ long maxsize = 0;
+ const char *maxsize_envvar;
+ maxsize_envvar = getenv(DEBUGINFOD_MAXSIZE_ENV_VAR);
+ if (maxsize_envvar != NULL)
+ maxsize = atol (maxsize_envvar);
+
+ /* PR 27982: Add max time if DEBUGINFOD_MAXTIME is set. */
+ long maxtime = 0;
+ const char *maxtime_envvar;
+ maxtime_envvar = getenv(DEBUGINFOD_MAXTIME_ENV_VAR);
+ if (maxtime_envvar != NULL)
+ maxtime = atol (maxtime_envvar);
+ if (maxtime && vfd >= 0)
+ dprintf(vfd, "using max time %lds\n", maxtime);
+
+ /* Maxsize is valid*/
+ if (maxsize > 0)
+ {
+ if (vfd)
+ dprintf (vfd, "using max size %ldB\n", maxsize);
+ char *size_header = NULL;
+ rc = asprintf (&size_header, "X-DEBUGINFOD-MAXSIZE: %ld", maxsize);
+ if (rc < 0)
+ {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = debuginfod_add_http_header(c, size_header);
+ free(size_header);
+ if (rc < 0)
+ goto out;
+ }
add_default_headers(c);
/* Copy lowercase hex representation of build_id into buf. */
if (data == NULL)
{
rc = -ENOMEM;
- goto out0;
+ goto out1;
}
/* thereafter, goto out1 on error. */
if (data[i].handle == NULL)
{
rc = -ENETUNREACH;
- goto out2;
+ goto out1;
}
data[i].client = c;
if (!escaped_string)
{
rc = -ENOMEM;
- goto out1;
+ goto out2;
}
snprintf(data[i].url, PATH_MAX, "%s/%s/%s/%s", server_url,
build_id_bytes, type, escaped_string);
long loops = 0;
int committed_to = -1;
bool verbose_reported = false;
+ struct timespec start_time, cur_time;
+ if ( maxtime > 0 && clock_gettime(CLOCK_MONOTONIC_RAW, &start_time) == -1)
+ {
+ rc = errno;
+ goto out2;
+ }
+ long delta = 0;
do
{
+ /* Check to see how long querying is taking. */
+ if (maxtime > 0)
+ {
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &cur_time) == -1)
+ {
+ rc = errno;
+ goto out2;
+ }
+ delta = cur_time.tv_sec - start_time.tv_sec;
+ if ( delta > maxtime)
+ {
+ dprintf(vfd, "Timeout with max time=%lds and transfer time=%lds\n", maxtime, delta );
+ rc = -ETIME;
+ goto out2;
+ }
+ }
/* Wait 1 second, the minimum DEBUGINFOD_TIMEOUT. */
curl_multi_wait(curlm, NULL, 0, 1000, NULL);
if ((*c->progressfn) (c, pa, pb))
break;
}
+ /* Check to see if we are downloading something which exceeds maxsize, if set.*/
+ if (maxsize > 0 && target_handle)
+ {
+ long dl_size = 0;
+#ifdef CURLINFO_SIZE_DOWNLOAD_T
+ curl_off_t download_size_t;
+ if (curl_easy_getinfo(target_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
+ &download_size_t) == CURLE_OK)
+ dl_size = download_size_t >= (double)(LONG_MAX+1UL) ? LONG_MAX : (long)download_size_t;
+#else
+ double download_size;
+ if (curl_easy_getinfo(target_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+ &download_size) == CURLE_OK)
+ dl_size = download_size >= (double)(LONG_MAX+1UL) ? LONG_MAX : (long)download_size;
+#endif
+ if (dl_size > maxsize)
+ {
+ if (vfd >=0)
+ dprintf(vfd, "Content-Length too large.\n");
+ rc = -EFBIG;
+ goto out2;
+ }
+ }
} while (still_running);
/* Check whether a query was successful. If so, assign its handle
if (msg->data.result != CURLE_OK)
{
+ long resp_code;
+ CURLcode ok0;
/* Unsuccessful query, determine error code. */
switch (msg->data.result)
{
case CURLE_SEND_ERROR: rc = -ECONNRESET; break;
case CURLE_RECV_ERROR: rc = -ECONNRESET; break;
case CURLE_OPERATION_TIMEDOUT: rc = -ETIME; break;
+ case CURLE_HTTP_RETURNED_ERROR:
+ ok0 = curl_easy_getinfo (msg->easy_handle,
+ CURLINFO_RESPONSE_CODE,
+ &resp_code);
+ /* 406 signals that the requested file was too large */
+ if ( ok0 == CURLE_OK && resp_code == 406)
+ rc = -EFBIG;
+ else
+ rc = -ENOENT;
+ break;
default: rc = -ENOENT; break;
}
}
if (efd >= 0)
close(efd);
}
+ else if (rc == -EFBIG)
+ goto out2;
/* If the verified_handle is NULL and rc != -ENOENT, the query fails with
* an error code other than 404, then do several retry within the retry_limit.
}
*ptr = NULL; /* reset when done */
+ const char *maxsize_string = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "X-DEBUGINFOD-MAXSIZE");
+ long maxsize = 0;
+ if (maxsize_string != NULL && maxsize_string[0] != '\0')
+ maxsize = atol(maxsize_string);
+ else
+ maxsize = 0;
+
#if MHD_VERSION >= 0x00097002
enum MHD_Result rc;
#else
if (r == 0)
throw reportable_exception("internal error, missing response");
+ if (maxsize > 0 && http_size > maxsize)
+ {
+ MHD_destroy_response(r);
+ throw reportable_exception(406, "File too large, max size=" + std::to_string(maxsize));
+ }
+
rc = MHD_queue_response (connection, MHD_HTTP_OK, r);
http_code = MHD_HTTP_OK;
MHD_destroy_response (r);
testrun ${abs_builddir}/debuginfod_build_id_find -e F/p+r%o\$g 1
########################################################################
+## PR27892
+# Ensure DEBUGINFOD_MAXSIZE is functional and sends back the correct http
+# code
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_RETRY_LIMIT=1 DEBUGINFOD_URLS="http://127.0.0.1:$PORT1/" DEBUGINFOD_MAXSIZE=1 \
+ ${abs_top_builddir}/debuginfod/debuginfod-find -v debuginfo F/p+r%o\$g.debug 2> find-vlog$PORT1 || true
+tempfiles find-vlog$PORT1
+# wait for the server to fail the same number of times the query is retried.
+wait_ready $PORT1 'http_responses_after_you_milliseconds_count{code="406"}' 1
+# ensure all reporting is functional
+grep 'serving file '$(realpath ${PWD})'/F/p+r%o\$g.debug' vlog$PORT1
+grep 'File too large' vlog$PORT1
+grep 'using max size 1B' find-vlog$PORT1
+if [ -f ${DEBUGINFOD_CACHE_PATH}/${BUILDID} ]; then
+ echo "File cached after maxsize check"
+ err
+fi
+# Ensure DEBUGINFOD_MAXTIME is functional
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS="http://127.0.0.1:8002/" DEBUGINFOD_MAXTIME=1 \
+ ${abs_top_builddir}/debuginfod/debuginfod-find -v debuginfo F/p+r%o\$g.debug 2> find-vlog$PORT1 || true
+grep 'using max time' find-vlog$PORT1
+# Ensure p+r%o\$g.debug is NOT cached
+if [ -f ${DEBUGINFOD_CACHE_PATH}/${BUILDID} ]; then
+ echo "File cached after maxtime check"
+ err
+fi
+########################################################################
# PR25628
rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests