upnpsoap: Return truncated results on full buffer

If our response buffer fills up to the max buffer size on a UPnP Browse
request, we should return short results rather than erroring out.

Fixes: #314 (Cannot browse MiniDLNA 1.2.1 with VLC 2.2.6 (UPnPError 709: Unsupported or invalid sort criteria))
This commit is contained in:
Justin Maggard 2019-12-09 21:10:10 -08:00 committed by Justin Maggard
parent ca6dbba183
commit 8f14d7223d
2 changed files with 23 additions and 12 deletions

View File

@ -40,7 +40,8 @@
#define FLAG_SKIP_DLNA_PN 0x00002000 /* during browsing */ #define FLAG_SKIP_DLNA_PN 0x00002000 /* during browsing */
#define FLAG_CONVERT_MS 0x00004000 /* convert ms to s */ #define FLAG_CONVERT_MS 0x00004000 /* convert ms to s */
/* Response-related flags */ /* Response-related flags */
#define FLAG_HAS_CAPTIONS 0x80000000 #define FLAG_HAS_CAPTIONS 0x10000000
#define RESPONSE_TRUNCATED 0x80000000
#define RESPONSE_FLAGS 0xF0000000 #define RESPONSE_FLAGS 0xF0000000
enum match_types { enum match_types {

View File

@ -858,15 +858,17 @@ callback(void *args, int argc, char **argv, char **azColName)
} }
else else
{ {
DPRINTF(E_ERROR, L_HTTP, "UPnP SOAP response was too big, and realloc failed!\n"); DPRINTF(E_ERROR, L_HTTP, "UPnP SOAP response truncated, realloc failed\n");
return -1; passed_args->flags |= RESPONSE_TRUNCATED;
return 1;
} }
#if MAX_RESPONSE_SIZE > 0 #if MAX_RESPONSE_SIZE > 0
} }
else else
{ {
DPRINTF(E_ERROR, L_HTTP, "UPnP SOAP response cut short, to not exceed the max response size [%lld]!\n", (long long int)MAX_RESPONSE_SIZE); DPRINTF(E_ERROR, L_HTTP, "UPnP SOAP response would exceed the max response size [%lld], truncating\n", (long long int)MAX_RESPONSE_SIZE);
return -1; passed_args->flags |= RESPONSE_TRUNCATED;
return 1;
} }
#endif #endif
} }
@ -1478,12 +1480,19 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
DPRINTF(E_DEBUG, L_HTTP, "Browse SQL: %s\n", sql); DPRINTF(E_DEBUG, L_HTTP, "Browse SQL: %s\n", sql);
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg); ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
} }
if( (ret != SQLITE_OK) && (zErrMsg != NULL) ) if( ret != SQLITE_OK )
{ {
DPRINTF(E_WARN, L_HTTP, "SQL error: %s\nBAD SQL: %s\n", zErrMsg, sql); if( args.flags & RESPONSE_TRUNCATED )
sqlite3_free(zErrMsg); {
SoapError(h, 709, "Unsupported or invalid sort criteria"); sqlite3_free(zErrMsg);
goto browse_error; }
else
{
DPRINTF(E_WARN, L_HTTP, "SQL error: %s\nBAD SQL: %s\n", zErrMsg, sql);
sqlite3_free(zErrMsg);
SoapError(h, 709, "Unsupported or invalid sort criteria");
goto browse_error;
}
} }
sqlite3_free(sql); sqlite3_free(sql);
/* Does the object even exist? */ /* Does the object even exist? */
@ -1936,9 +1945,10 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
orderBy, StartingIndex, RequestedCount); orderBy, StartingIndex, RequestedCount);
DPRINTF(E_DEBUG, L_HTTP, "Search SQL: %s\n", sql); DPRINTF(E_DEBUG, L_HTTP, "Search SQL: %s\n", sql);
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg); ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
if( (ret != SQLITE_OK) && (zErrMsg != NULL) ) if( ret != SQLITE_OK )
{ {
DPRINTF(E_WARN, L_HTTP, "SQL error: %s\nBAD SQL: %s\n", zErrMsg, sql); if( !(args.flags & RESPONSE_TRUNCATED) )
DPRINTF(E_WARN, L_HTTP, "SQL error: %s\nBAD SQL: %s\n", zErrMsg, sql);
sqlite3_free(zErrMsg); sqlite3_free(zErrMsg);
} }
sqlite3_free(sql); sqlite3_free(sql);